texlive[70976] Master: l3kernel-dev

commits+karl at tug.org commits+karl at tug.org
Thu Apr 18 21:48:25 CEST 2024


Revision: 70976
          https://tug.org/svn/texlive?view=revision&revision=70976
Author:   karl
Date:     2024-04-18 21:48:25 +0200 (Thu, 18 Apr 2024)
Log Message:
-----------
l3kernel-dev

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/tlpsrc/00texlive.autopatterns.tlpsrc
    trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
    trunk/Master/tlpkg/tlpsrc/latex-bin-dev.tlpsrc
    trunk/Master/tlpkg/tlpsrc/platex.tlpsrc
    trunk/Master/tlpkg/tlpsrc/uplatex.tlpsrc
    trunk/Master/tlpkg/tlpsrc/xelatex-dev.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/CHANGELOG.md
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/README.md
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/expl3.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3doc.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3docstrip.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3obsolete.txt
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.csv
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.pdf
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.tex
    trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3body.tex
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/expl3.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3.ins
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3basics.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bitset.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bootstrap.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3box.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3cctab.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3clist.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3coffins.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3color.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3debug.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3deprecation.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3doc.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3docstrip.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3expan.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3file.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3flag.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-assign.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-aux.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-basics.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-convert.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-expo.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-extended.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-functions.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-logic.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-parse.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-random.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-round.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-symbolic.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-traps.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-trig.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp-types.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fp.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3fparray.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3int.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3intarray.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3kernel-functions.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3keys.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3legacy.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3luatex.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3msg.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3names.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3pdf.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3prg.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3prop.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3quark.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3regex.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3seq.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3skip.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3sort.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3str-convert.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3str.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3sys.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3text-case.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3text-map.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3text-purify.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3text.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3tl-analysis.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3tl-build.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3tl.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3token.dtx
    trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3unicode.dtx
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/expl3-code.tex
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/expl3-generic.tex
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/expl3.ltx
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/expl3.lua
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/expl3.sty
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3debug.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3doc.cls
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3docstrip.tex
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88591.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso885910.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso885911.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso885913.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso885914.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso885915.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso885916.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88592.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88593.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88594.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88595.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88596.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88597.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88598.def
    trunk/Master/texmf-dist/tex/latex-dev/l3kernel/l3str-enc-iso88599.def
    trunk/Master/tlpkg/tlpsrc/l3kernel-dev.tlpsrc

Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/CHANGELOG.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/CHANGELOG.md	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,1879 @@
+# Changelog
+All notable changes to the `l3kernel` bundle since the start of 2018
+will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+this project uses date-based 'snapshot' version identifiers.
+
+## [Unreleased]
+
+## [2024-04-11]
+
+### Added
+- `\prop_(g)put_if_not_in:Nnn` (renamed from `\prop_(g)put_if_new:Nnn`)
+- `\intarray_if_exist:N(TF)`
+- `\fparray_if_exist:N(TF)`
+- Support for 'indexed' PDF objects
+
+### Changed
+- Expand object names in `\pdf_object_...` functions (issue \#1521)
+- Adapt `l3doc` for `ltcmd` change to handling of newlines
+  (see latex3/latex2e\#1304)
+- Return active spaces from `\sys_get_query:n(nn)N` (issue \#1529)
+
+### Fixed
+- False `debug` error raised by `\cctab_const:Nn` (issue \#1508)
+- Undefined `\__kernel_iwo_open:Nn` used in `\iow_shell_open:Nn`
+  (issue \#1515)
+- Naming of register functions in LuaMetaTeX 2.11+ (issue \#1518)
+- Catcode applied to letters by `\sys_get_query:n(nn)N`
+
+### Deprecated
+- `\prop_(g)put_if_new:Nnn` (renamed to `\prop_(g)put_if_not_in:Nnn`)
+
+## [2024-03-14]
+
+### Added
+- Macro interface for `l3sys-query`
+
+### Changed
+- Require that `expl3` is loaded at top level in generic mode
+- Ensure that the dimension arguments to `\box_autosize_to_...:Nnn`
+  are properly formed (issue \#1502)
+
+### Fixed
+- Typeset `TF` of internal conditionals in current color (issue \#730)
+- Some functions and variables were defined locally
+
+## [2024-02-20]
+
+### Changed
+- Improve error recovery when an invalid `prop` is used (PR \#1464) 
+
+### Fixed
+- Restore `\__kernel_msg_...:nnx(xx)` for older `xparse` support
+- Prevent an infinite loop in `\debug_(on|off):n` (issue \#1442)
+- Require `\sys_ensure_backend:` is used in the preamble (issue \#1442)
+
+## [2024-02-18]
+
+### Changed
+- Work-around to enable `\prop_set_from_keyval:Nn`, etc., to avoid an error if
+  `prop` is not already defined
+
+### Fixed
+- Extend debug checking to cover `\prop_(g)set_from_keyval:Nn`
+
+## [2024-02-13]
+
+### Added
+- Checking missing `\endgroup` at the end of `\DocInclude`
+- Linked storage type for large property lists (issue \#1040, pull \#1059)
+
+### Changed
+- `\meta` now typesets in `\texttt`, along with `\Arg`
+- Improved the performance of `\cs_if_exist:NTF`, `\cs_if_free:NTF`,
+    `\cs_if_exist_use:NTF`, and most notably their `c`-type variants.
+
+### Fixed
+- Inconsistent local/global assignments in `\vcoffin_gset:Nnn` and
+  `\vcoffin_gset:Nnw`
+- Tokenization by `\peek_analysis_map_inline:n` of one additional
+  character after any space or brace
+
+### Deprecated
+- `\msg_gset:nnn(n)`
+
+## [2024-01-22]
+
+### Added
+- `\keys_set_exclude_groups:nnn(nN)` to replace `\keys_set_filter:nnn(nN)`
+- Flags with N-type names, like other variable types
+
+### Changed
+- Set `l3doc` option `kernel` off as-standard (issue \#1403)
+- Moved `\seq_set_filter:NNn` to stable
+
+### Deprecated
+- `\keys_set_filter:nnn(nN)` in favor of  `\keys_set_exclude_groups:nnn(nN)`
+
+## [2024-01-04]
+
+### Added
+- Documentation for `\bitset_show_named_index:N` (issue \#1372)
+- `\bitset_log_named_index:N`
+- `\tl_build_get_intermediate:NN`
+- Support for `.default:n` values for the `unknown` handler (see issue \#67)
+
+### Changed
+- Improved method to suppress `l3bitset` where required
+- Clarify behavior of `\tl_if_novalue:n(TF)` (see issue \#1402)
+
+### Deprecated
+- `\tl_build_get:NN` in favor of `\tl_build_get_intermediate:NN`
+
+### Fixed
+- Handling of `documented-as` variants in `l3doc` indexing
+  (see issue \#1345)
+- Missing trailing `TF` in single variant of conditional functions (issue \#1398)
+
+## [2023-12-11]
+
+### Changed
+- Use keyval handler for `l3doc` class options
+
+### Fixed
+- Support for deprecated `pdf` module functions (issue \#1373)
+- Generate stub `l3bitset` for transitional support
+
+## [2023-12-08]
+
+### Added
+- `\c_empty_str` (issue \#1361)
+- `l3bitset`: moved from `l3experimental`
+
+### Fixed
+- Return `str` (not `tl`) in `\bool_to_str:N` and `\bool_to_str:n` (issue \#1331)
+- Catcode of space from `\str_set_convert:Nnnn` (issue \#1344)
+- Tidy up various documentation issues (issue \#1345)
+
+## [2023-11-09]
+
+### Added
+- Documentation for `\c_nan_fp`
+- `\str_case_e:en(TF)`
+
+### Changed
+- Speed up `\str_(g)set:Nn`, `\str_const:Nn`, `\str_(g)put_left:Nn`,
+  and `\str_(g)put_right:Nn`
+
+### Fixed
+- Normalisation of `.inherit:n` key data (issue \#1314)
+
+## [2023-11-01]
+
+### Added
+- `\seq_(g)set_map_e:NNn`
+- Documentation for `\ExplLoaderFileDate` in `expl3.pdf`
+
+### Changed
+- Documentation improvements
+- Refine action of `\text_titlecase_first:n(n)` to be focussed strictly on
+  first (relevant) codepoint in the input
+- Standardize "This is the (e)TeX primitive ..." in `texnote` in documentation
+- Move `\tl_build_(g)begin:N`, `\tl_build_(g)end:N`, `\tl_build_(g)put_left:Nn`
+  and `\tl_build_(g)right:Nn` to stable status
+
+### Deprecated
+- `\seq_(g)set_map_x:NNn` in favor of `e`-type naming
+
+### Fixed
+- `\fp_clear_variable:n` should act locally (issue \#1298)
+- `\fp_clear_function:n` should act locally and correctly
+- Support for `\fp_show:N` showing symbolic expressions (issue \#1301)
+- Undefined `\str_case:en(TF)` (excluding `\str_case:en`)
+
+## [2023-10-23]
+
+### Added
+- `\text_titlecase_all:n(n)`
+- `\token_to_catcode:N`
+- Support for symbolic variables in fp input:
+  `\fp_new_variable:n`, `\fp_set_variable:nn` and `\fp_clear_variable:n`
+- Support for user-defined functions in fp expressions:
+  `\fp_new_function:n`, `\fp_set_function:nnn` and `\fp_clear_function:n`
+
+### Changed
+- Clarify action of `\text_titlecase_first:n(n)`
+- Detect letters for titlecasing based on Unicode general category
+
+### Deprecated
+- `\text_titlecase:n(n)` as ambiguous: replaced by `\text_titlecase_all:n(n)`
+- `\tl_build_(g)clear:N` in favour of `\tl_build_(g)begin:N`
+
+### Fixed
+- Support arbitrary BCP-47 locales for case-changing overrides (issue \#1239)
+- Retain braces when ending titlecasing with some input structures
+
+## [2023-10-10]
+
+### Added
+- `\iow_shipout_e:Nn`
+- Documentation for `\sys_if_timer_exist_p:` and `\sys_if_timer_exist:(TF)`.
+  They were supported since l3kernel 2021-05-25, along with `\sys_timer:`.
+- l3doc.dtx: Support for footnotes in the function and variable environment  
+- Variants `\tl_if_single:c(TF)` and `\tl_if_single_p:c` (issue \#1272)
+- Key properties `.str_(g)set_e:N` and `.tl_(g)set_e:N`
+
+### Changed
+- Switch generally from `x`- to `e`-type variants
+- Convert `\file_if_exist:n(TF)` to expandable status,
+  adding predicate version
+- Standardise variants for `\prop_(g)pop:NnN(TF)`
+- Standardise variants for `\prop_(g)put:Nnn`
+- Standardise variants for `\prop_(g)put_if_new:Nnn`
+- Standardise variants for `\prop_(g)remove:Nn`
+
+### Deprecated
+- `\iow_shipout_x:Nn` in favor of `e`-type naming
+- Key properties `.str_(g)set_x:N` and `.tl_(g)set_x:N`
+
+### Fixed
+- Rare rounding error in divisions (issue \#1264)
+
+## [2023-08-29]
+
+### Added
+- `\c_sys_timestamp_str`
+
+### Changed
+- Rename `\tex_pdfcreationdate:D` to `\tex_creationdate:D`
+
+## [2023-08-11]
+
+### Changed
+- Wrap long lists of variants in `l3doc` display of functions (issue \#1258)
+
+### Fixed
+- Revert 'Allow for implicit chars when case changing' (issue \#1260)
+
+## [2023-08-03]
+
+### Added
+- `\tex_XeTeXhyphenatablelength:D`, `\tex_XeTeXinterwordspaceshaping:D`,
+  `\tex_XeTeXselectorcode:D`
+- Several missing `\tex_<name>:D` primitives from LuaTeX and (up)TeX
+
+### Changed
+
+- `\tex_protrudechars:D` now defined for XeTeX (to `\XeTeXprotrudechars`)
+- Allow for optional `v` in version string argument to
+  `\ProvidesExpl...`
+
+### Fixed
+- Allow for implicit chars when case changing
+
+## [2023-06-30]
+
+### Added
+- `\codepoint_to_category:n`
+
+### Changed
+- Drop notes about slow `\expanded` emulation. `\expanded` is required since
+  release 2023-05-15
+- Sync engine/primitive requirements in `expl3.dtx` with code and README
+
+### Fixed
+- Case changing of Greek characters with complex NFD representation (issue \#1236)
+- Error recovery when wrongly applying abs to a tuple (issue \#1238)
+
+## [2023-06-16]
+
+### Changed
+- Exclude entries in `\l_text_case_exclude_arg_tl` from expansion in `\text_expand:n`
+  (latex3/latex2e\#904)
+- Generate _dialytika_ if appropriate when uppercasing Greek words starting with a
+  vowel taking a breathing mark (issue \#1228)
+- Retain stress diacritics when uppercasing Greek (issue \#1230)
+- Expand (partial) paths in `\l_file_search_path_seq` and `\input at path`
+  (see latex3/latex2e\#1086)
+
+## [2023-06-05]
+
+### Added
+- `\cctab_gsave_current:N`, `\g_tmpa_cctab` and `\g_tmpb_cctab` (issue \#1089)
+- `\prg_gset_eq_conditional:NNn` (issue \#1212)
+- `\iow_shell_open:Nn` (issue \#1122)
+
+### Deprecated
+- `\tl_case:Nn(TF)`
+- `expl3` package option `enable-debug` (no longer required)
+
+### Fixed
+- Set `\l_keys_value_tl` in `.initial:n` (issue \#1013)
+- Support for boolean values in `expl3` package options
+  `check-declarations` and `log-functions` (issue \#978)
+- Allow for optional `/` at end of `\input at path` entries
+  (see latex3/latex2e\#1076)
+
+## [2023-05-22]
+
+### Added
+- Rounded out the `\use_i:nn...` functions to cover all cases taking
+  one argument from up to nine arguments
+- `\coffin_(g)reset_poles:N`
+- `\dim_to_decimal_in_<unit>:n`, for `<unit>` types
+  `cc`, `cm`, `dd`, `in`, `mm` and `pc`
+- `\file_input_raw:n`
+- `\int_if_zero:n(TF)`
+- `\str_mdfive_hash:n`
+### Changed
+- Remove `\noexpand` inside math mode in `\text_expand:n`
+- Re-implement `\dim_to_decimal_in_bp:n` and 
+  `\dim_to_decimal_in_unit:nn` to be re-entrant (issue \#954)
+
+### Fixed
+- Omit `0123456789` from URL escaping (issue \#838)
+- Leave implicit chars unchanged in `\text_expand:n` (issue \#874)
+- Filtering/grouping applied to meta keys (issue \#940)
+- Issue correct error message if `bool` key is set
+  incorrectly using `.initial:n` (issue \#1013)
+- Set `\l_keys_key_str` in `.initial:n` (issue \#1013)
+- Handling of implicit chars in `\text_purify:n` (issue \#1208)
+
+## [2023-05-15]
+
+### Changed
+- Require `\expanded` and 'pdfTeX extension' primitives,
+  and thus TeX distributions from mid-2019 onward
+
+### Fixed
+- Treatment of trailing `/` in `\input at path`
+
+## [2023-05-11]
+
+### Added
+- `\seq_map_pairwise_function:NNN` (renamed from  `\seq_mapthread_function:NNN`)
+
+### Changed
+- Moved `\seq_set_item:Nnn` to stable status
+- Track seen filenames to improve performance of
+  `\file_full_name:n` and dependent file operations
+
+### Removed
+- Experimental function `\seq_pop_item:NnN` from `l3candidates`
+- Experimental function `\seq_mapthread_function:NNN` now renamed
+  `\seq_map_pairwise_function:NNN`
+
+## [2023-05-05]
+
+### Added
+- `\bool_case:n(TF)` (renamed from  `\bool_case_true:n(TF)`)
+- `\flag_ensure_raised:n` (renamed from `\flag_raise_if_clear:n`)
+- `\iow_wrap_allow_break:` (renamed from `\iow_allow_break:`)
+
+### Changed
+- Moved to stable status:
+  - `\bool_(g)set_inverse:N`
+  - `\c_catcode_active_space_tl`
+  - `\c_sys_engine_version_str`
+  - `\exp_args_generate:n`
+  - `\fp_if_nan:n(TF)`
+  - `\ior_get_term:nN` and `\ior_str_get_term:nN`
+  - `\ior_shell_open:Nn`
+  - `\msg_show_item:n`, `\msg_show_item_unbraced:n`,
+    `\msg_show_item:nn`, `\msg_show_item_unbraced:nn`
+- Require random number support from engine
+
+### Removed
+- Experimental functions from `l3candidates`:
+  - `\bool_case_false:n(TF)`
+  - `\intarray_gset_rand:Nn(n)`
+  - `\intarray_to_clist:N`
+  - `\peek_catcode_collect_inline:Nn`, `\peek_charcode_collect_inline:Nn` and
+    `\peek_meaning_collect_inline:Nn`
+  - `\prop_rand_key_value:N`
+  - `\seq_set_from_function:Nnn` and `\seq_set_from_inline_x:Nnn`
+  - `\sys_if_rand_exist:(TF)`
+  - `\tl_range_braced:Nnn` and `\tl_range_unbraced:Nnn`
+- Experimental functions now renamed
+  - `\bool_case_true:n(TF)` (now `\bool_case:n(TF)`)
+  - `\flag_raise_if_clear:n` (now `\flag_ensure_raised:n`)
+  - `\iow_allow_break:` (now `\iow_wrap_allow_break:`)
+- Experimental functions moved to kernel-internal:
+  - `\msg_log_eval:Nn` and `\msg_show_eval:Nn`
+
+## [2023-04-20]
+
+### Changed
+- Re-order arguments of `\text_declare_lowercase_mapping:nnn`,
+  `\text_declare_titlecase_mapping:nnn` and
+  `\text_declare_uppercase_mapping:nnn`
+
+## [2023-04-19]
+
+### Added
+- `\box_set_clipped:N` and variants (renamed from `\box_clip:N`)
+- `\text_declare_lowercase_mapping:nn(n)`,
+   `\text_declare_titlecase_mapping:nn(n)`
+   and `\text_declare_uppercase_mapping:nn(n)` to allow customization of
+   case changing outcomes
+
+### Changed
+- `\box_set_trim:Nnnnn` and `\box_set_viewport:Nnnnn` moved to
+  stable kernel
+
+### Fixed
+- Incorrect internal name in `\pdf_pagesize_gset:nn`
+
+### Removed
+- Experimental `\box_clip:N` and variants (renamed to 
+  `\box_set_clipped:N`)
+
+## [2023-03-30]
+
+### Added
+- `\tex_endlocalcontrol:D` as expl3 name for the LuaTeX primitive
+
+### Changed
+- Allow non-integer values in color expressions
+- Restrict color expressions values to the range [0, 100]
+- Leave Greek spacing diacritics unchanged in uppercasing
+
+### Fixed
+- Fix minor version in `\c_sys_engine_version_str` for pdfTeX and LuaTeX
+  (issue [\#1186](https://github.com/latex3/latex3/issues/1186))
+
+## [2023-02-22]
+
+### Changed
+- More defensive approach in `\codepoint_to_nfd:n`
+
+### Fixed
+- CJK character handling for (u)pTeX (issue
+  [\#1171](https://github.com/latex3/latex3/issues/1171))
+
+## [2023-02-07]
+
+### Changed
+- Swap meaning of `el` and `el-x-iota` when case changing
+  Greek: match traditional LaTeX approach
+
+### Deprecated
+- `\l_text_accents_tl` and `\l_text_letterlike_tl`
+
+## [2023-02-02]
+
+### Fixed
+- Handling of multiple accents when uppercasing Greek
+  (see LaTeX2e issue
+  [\#987](https://github.com/latex3/latex2e/issues/987))
+
+## [2023-02-01]
+
+### Fixed
+- Allow for expressions within color `RGB`/`HSB` input
+
+## [2023-01-24]
+
+### Added
+- Complete list of pdfTeX primitives
+
+### Fixed
+- Allow for multi-part BCP47 strings in case changing
+- Loading with plain TeX due to `\outer` status of `^^L`
+  issue ([\#1161](https://github.com/latex3/latex3/issues/1161))
+
+### Changed
+- Leave catcode of `&` unchanged in code environment
+
+## [2023-01-16]
+
+### Added
+- `\pdf_pagesize_gset:nn`
+
+### Fixed
+- Enable `\char_generate:nn` to create active tokens which are `\outer`
+  or equal to `\fi`
+
+## [2022-12-17]
+
+### Added
+- `\codepoint_to_nfd:n`
+- `\codepoint_generate:n` and `\codepoint_str_generate:n`
+- `\str_casefold:n`
+
+### Changed
+- Protect `babel` shorthands from expansion
+
+### Fixed
+- Appearance of `\DescribeOption` (issue
+  [\#1111](https://github.com/latex3/latex3/issues/1111))
+
+## [2022-11-02]
+
+### Added
+- `\prg_gset_conditional:N(p)nn` and 
+  `\prg_gset_protected_conditional:N(p)nn`
+
+### Fixed
+- Loading of `expl3` with ConTeXt MkIV (issue
+  [\#1142](https://github.com/latex3/latex3/issues/1142))
+
+## [2022-10-26]
+
+### Changed
+- Usage of `\exp_not:n`/`\exp_not:N` in `\peek_analysis_map_inline:n` output
+
+### Fixed
+- `\peek_analysis_map_inline:n` support for macro parameter characters (issue
+  [\#1109](https://github.com/latex3/latex3/issues/1109)), for many expandable
+  tokens (issue [\#1110](https://github.com/latex3/latex3/issues/1110)), and an
+  esoteric case (issue [\#1113](https://github.com/latex3/latex3/issues/1113))
+- Creation of a message with some engines (issue
+  [\#1139](https://github.com/latex3/latex3/issues/1139))
+
+### Deprecated
+- `\char_to_nfd:N`, `\char_to_nfd:n`
+- `\char_foldcase:N`, `\char_lowercase:N`, `\char_titlecase:N`,
+   `\char_uppercase:N` and `str` variants
+- `\char_to_utfviii_bytes:n`
+- `\str_foldcase:n`
+
+## [2022-09-28]
+
+### Added
+- Set media box for test phase documents
+
+### Fixed
+- Text case switching in `\text_titlecase_first:n` (issue
+  [\#1130](https://github.com/latex3/latex3/issues/1130))
+
+## [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 medieval Latin case changing
+- `\char_to_nfd:n` to extend NFD support to 8-bit engines
+
+### Deprecated
+- `\pdf_object_new:nn` and `\pdf_object_write:nn`, in favor of
+  `\pdf_object_new:n` and `\pdf_object_write:nnn`, respectively
+
+## [2022-08-23]
+
+### Added
+- Shortened range of chars which are left unchanged when converted to
+  strings with `\str_(g)set_convert:Nnnn`. 
+- `\color_if_exist:n(TF)`
+- Support for case changing Vietnamese characters with 8-bit engines
+- Parsing of `cmy`, `tHsb` and `&spot` color models to support data exchange with
+  `xcolor`
+
+### Changed
+- Replace `LaTeX3` in message text by `LaTeX`
+
+### Changed
+- Approach to setting current color data from LaTeX2e
+## [2022-08-05]
+
+### Added
+- Support for case changing Croatian diagraph with 8-bit engines
+- Support accent removal when uppercasing Greek with 8-bit engines
+- Function `\sys_ensure_backend:`
+
+### Fixed
+- Behavior of `\color_math:nn` in alignments
+- Expansion of text containing unterminated `\romannumeral` primitives
+
+## [2022-07-21]
+
+### Fixed
+- `\iow_open:N` in ConTeXt MkII
+
+## [2022-07-15]
+
+### Fixed
+- Correct argument order in `\text_case_switch:nnnn`
+
+## [2022-07-14]
+
+### Changed
+- Improved approach to `\text_case_switch:nnnn` expansion
+
+## [2022-07-04]
+
+### Added
+- `\text_declare_case_equivalent:Nn`, `\text_case_switch:nnnn` and
+  related mechanism to allow specialisation of case changing output
+  for selected commands
+
+## [2022-07-01]
+
+### Added
+- `\cs_parameter_spec:N`
+
+### Changed
+- `\text_expand:n` now acts on active chars to support legacy input encodings
+
+### Deprecated
+- `\cs_argument_spec:N`
+
+### Fixed
+- Correct validity check performed by `\regex_show:N` (issue [\#1093](https://github.com/latex3/latex3/issues/1093))
+- Closing of file handles (issue [\#1105](https://github.com/latex3/latex3/issues/1105))
+
+## [2022-06-16]
+
+### Fixed
+- Made `\peek_analysis_map_inline:n` alignment-safe (issue [\#1090](https://github.com/latex3/latex3/issues/1090))
+- Setting a boolean to itself no longer errors (issue [\#1055](https://github.com/latex3/latex3/issues/1055))
+
+## [2022-06-02]
+
+### Changed
+- Exclude only first mandatory argument of entries in
+  `\l_text_case_exclude_arg_tl` from case changing
+
+## [2022-05-30]
+
+### Added
+- Add `\lua_load_module:n`
+
+### Fixed
+- Typo in implementation of titlecase `hy-x-yiwn`
+- Definition order issue with `\str_case:Nn(TF)`
+
+## [2022-05-04]
+
+### Added
+- Language settings `hy` and `hy-x-yiwn` for handling of ech-yiwn ligature
+  uppercasing
+
+### Changed
+- Support BCP 47 properly in case changer language argument
+
+### Fixed
+- Correct `el-xiota` and `de-xeszett` to `el-x-iota` and `de-x-eszett`
+
+## [2022-04-29]
+
+### Added
+- Language setting `el-xiota` for retention of ypogegrammeni when uppercasing
+  Greek
+
+### Changed
+- Rename case-changing variant `de-alt` to `de-xeszett` to align with
+  `luaotfload`
+- Allow for `\lccode`/`\uccode` changes in `\char_...case:n` functions
+
+### Fixed
+- Support for ypogegrammeni in case changing Greek (see issue [\#1088](https://github.com/latex3/latex3/issues/1088))
+
+## [2022-04-20]
+
+### Changed
+- Collect some common code from `l3backend-color`
+
+## [2022-04-10]
+
+### Added
+- `\keys_precompile:nnN` for conversion of keyvals to fast-to-apply token
+  lists
+- Missing `\str_if_empty:n(TF)` (see issue [\#1071](https://github.com/latex3/latex3/issues/1071))
+- Missing `\str_case:Nn(TF)` (see issue [\#1071](https://github.com/latex3/latex3/issues/1071))
+- `\tex_...:D` names for primitives added in TeX Live 2022
+
+### Changed
+- Definition of `\legacy_if:n(TF)` to support primitive conditionals
+- `\str_<type>case:n` now case changes codepoints above 127 with all engines
+- `\char_generate:nn` now also allows to generate category 10 tokens (spaces)
+  except for char code 0
+
+### Fixed
+- Handling of 'misplaced' `\protect` by `\text_expand:n`
+- Nesting of `\tl_analysis_map_inline:nn`
+- Naming of an error message
+
+## [2022-02-24]
+
+### Changed
+- Better support for `\cite`, _etc._, in case changing
+
+## [2022-02-21]
+
+### Fixed
+- Use of `\@uclclist` for case changing
+
+## [2022-02-05]
+
+### Added
+- Distribute `l3doc.pdf` with a prominent warning about future changes
+- `\color_math:nn(n)` as a functional equivalent of the new `\mathcolor`
+  command in LaTeX2e
+
+### Changed
+- Documentation for horizontal coffin poles (see issue [\#1041](https://github.com/latex3/latex3/issues/1041))
+- Update primitive requirements to enable loading with Prote/HINT
+
+## [2022-01-21]
+
+### Changed
+- Auto-generate legacy switch if required in `.legacy_set_if:n`
+  key property
+
+### Fixed
+- Correct creation of `.if` property
+- Handling of colors created in a group once they go out-of-scope
+
+## [2022-01-12]
+
+### Added
+- Support for validity scope for keys
+- `\peek_remove_filler:n`
+- `\prop_to_keyval:N`
+- `\regex_match_case:nn(TF)`, `\regex_replace_case_once:nN(TF)`,
+  `\regex_replace_case_all:nN(TF)`
+
+### Changed
+- Policy change: functions will no longer be removed after deprecation,
+  thus the Lua functions noted below are the *last* 'stable' code to be
+  removed from `l3kernel` after deprecation
+- Allow indirect conversions between colorspaces through fallback models
+- Move some color functions from `l3backend`
+
+### Deprecated
+- `\peek_..._ignore_spaces:N(TF)` functions
+- `\sys_load_deprecation:`
+- Option `undo-recent-deprecations`
+
+### Removed
+- Lua functions in `l3kernel` table
+
+## [2021-11-22]
+
+### Added
+- Support for legacy `if` switches in `l3keys`
+
+### Changed
+- Documentation improvements
+- Implementation of `intarray` data type with LuaTeX
+- Better support for LuaMetaTeX
+
+## [2021-11-12]
+
+### Fixed
+- DeviceN colorspace conversions with alternative model RGB
+
+### Added
+- `.str_set:N`, etc., key properties (issue [\#1007](https://github.com/latex3/latex3/issues/1007))
+- `\bool_to_str:n` (issue [\#1010](https://github.com/latex3/latex3/issues/1010))
+
+### Changed
+- `\prop_..._from_keyval:Nn` functions now support active comma or
+  equal sign (pull \#1012)
+
+## [2021-10-18]
+
+### Added
+- Support for ICC-based color profiles
+- `\color_profile_apply:nn`
+
+## [2021-10-17]
+
+### Changed
+- Better DeviceN support
+
+## [2021-10-12]
+
+### Fixed
+- Global assignments for `\box_gresize_to_ht_plus_dp:Nn`
+  and `\coffin_gattach:NnnNnnnn`
+- Conversion of DeviceN colors to device fallback
+
+## [2021-08-27]
+
+### Changed
+- Formatting of expandable errors (issue [\#931](https://github.com/latex3/latex3/issues/931))
+- Internal code for kernel messages
+
+## [2021-07-12]
+
+### Fixed
+- Handling of multiple color models (issue [\#962](https://github.com/latex3/latex3/issues/962))
+
+### Removed
+- Functions marked for removal end-2020
+
+## [2021-06-18]
+
+### Fixed
+- Local assignment to `\g__sys_backend_tl`
+- Incorrect internal function name (issue [\#939](https://github.com/latex3/latex3/issues/939))
+- Case-changing exceptions for (u)pTeX (issue [\#939](https://github.com/latex3/latex3/issues/939))
+- Low-level error if accent commands are not followed by
+  letter when case changing (see \#946)
+
+## [2021-06-01]
+
+### Fixed
+- Loading when `\expanded` is not available
+
+## [2021-05-27]
+
+### Fixed
+- Correctly detect local formats in `Mismatched LaTeX support files` error.
+
+## [2021-05-25]
+
+### Added
+- `\msg_note:nnnnnn` (issue [\#911](https://github.com/latex3/latex3/issues/911))
+- `\str_compare:nNnTF` (issue [\#927](https://github.com/latex3/latex3/issues/927))
+- `\sys_timer:`
+- `\prop_concat:NNN`, `\prop_put_from_keyval:Nn` (issue [\#924](https://github.com/latex3/latex3/issues/924))
+- Functions to show and log various datatypes (issue [\#241](https://github.com/latex3/latex3/issues/241)):
+  `\coffin_show:Nnn`, `\coffin_show:N`, `\coffin_log:Nnn`, `\coffin_log:N`,
+  `\color_log:n`, `\group_show_list:`, `\group_log_list:`,
+  `\ior_show:N`, `\ior_log:N`, `\iow_show:N`, `\iow_log:N`,
+  `\tl_log_analysis:N`, `\tl_log_analysis:n`
+- `\legacy_if_set_true:n`, `\legacy_if_set_false:n`, `\legacy_if_set:nn`
+- Matching multiple regex at the same time (issue [\#433](https://github.com/latex3/latex3/issues/433)):
+  `\regex_case_match:nn(TF)`,
+  `\regex_case_replace_once:nN(TF)`,
+  `\regex_case_replace_all:nN(TF)`
+
+### Fixed
+- Checking brace balance in all regex functions (issue [\#377](https://github.com/latex3/latex3/issues/377))
+- Removing duplicates in clists when items contain commas (issue [\#917](https://github.com/latex3/latex3/issues/917))
+
+### Changed
+- Slight speed up in some elementary int/dim/skip/muskip operations and
+  in setting tl or clist variables equal.
+- Speed up mapping functions in l3clist, l3prop, l3seq, l3tl
+
+## [2021-05-11]
+
+### Added
+- `\cctab_item:Nn` (issue [\#880](https://github.com/latex3/latex3/issues/880))
+- `\clist_use:nnnn` and `\clist_use:nn` (issue [\#561](https://github.com/latex3/latex3/issues/561))
+
+### Fixed
+- Loading of backend in generic DVI mode (issue [\#905](https://github.com/latex3/latex3/issues/905))
+- Make `\keyval_parse:nnn` alignment-safe (issue [\#896](https://github.com/latex3/latex3/issues/896))
+- Control sequences and category codes in regex replacements (issue [\#909](https://github.com/latex3/latex3/issues/909))
+
+### Changed
+- Speed up `\group_align_safe_begin:` (pull \#906)
+
+## [2021-05-07]
+
+### Added
+- Color export in comma-separated format
+- `\ur{...}` escape in `l3regex` to compose regexes
+- `\seq_set_split_keep_spaces:Nnn` (see \#784)
+- `\seq_set_item:Nnn(TF)` and `\seq_pop_item:NnN(TF)`
+- `\box_ht_plus_dp:N` (issue [\#899](https://github.com/latex3/latex3/issues/899))
+- `\clist_map_tokens:nn`, `\clist_map_tokens:Nn`,
+  `\str_map_tokens:nn`, `\str_map_tokens:Nn`
+
+### Changed
+- Use prevailing catcodes instead of string in regex replacement (issue [\#621](https://github.com/latex3/latex3/issues/621))
+  (*Breaking change*)
+- `\__kernel_file_name_sanitize:n` now uses a faster `\csname`-based
+  approach to expand the file name
+- Improved performance for basic conditionals
+- `\pdf_version_gset:n` support for `dvips`
+- Improve handling of `\exp_not:n` in `\text_expand:n` (issue [\#875](https://github.com/latex3/latex3/issues/875))
+- `\file_full_name:n` now avoids calling `\pdffilesize` primitive multiple times
+  on the same file
+- Show printable characters explicitly in `\regex_show:n`
+- Regex replacement now errors when using a submatch (`\1` etc) for which
+  the regex has too few groups
+- Showing complex datatypes now validates their internal structure (issue [\#884](https://github.com/latex3/latex3/issues/884))
+- Indexing in l3doc: all page references before codeline references,
+  improve target placement, solve pdfTeX and makeindex warnings
+
+### Fixed
+- Evalutate integer constants only once (issue [\#861](https://github.com/latex3/latex3/issues/861))
+- Detect `\ior_map_inline:Nn` calls on undefined streams (issue [\#194](https://github.com/latex3/latex3/issues/194))
+
+### Deprecated
+- `l3docstrip` converted to a stub which simply loads DocStrip: use
+   the latter directly
+
+## [2021-02-18]
+
+### Added
+- `l3color`: Moved from `l3experimental`
+- `l3pdf`: Moved from `l3experimental`
+- `default` alias to str_convert
+
+### Changed
+- Re-ordered `interface3` documentation
+- Moved `msg_show:nn(nnnn)` to stable
+
+## [2021-02-06]
+
+### Changed
+- Use new (internal) interface for kerns
+
+## [2021-02-02]
+
+### Added
+- `\c_zero_str`
+
+## [2021-01-09]
+
+### Added
+- `\keyval_parse:nnn`
+
+### Changed
+- `\keyval_parse:NNn` is set equal to `\keyval_parse:nnn`
+
+### Fixed
+- Handling of encoding-specfic commands in `\text_purify:n`
+
+## [2020-12-07]
+
+### Fixed
+- `\peek_analysis_map_inline:n` with spaces and braces
+
+## [2020-12-05]
+
+### Fixed
+- Setting of line width in vertical coffins in LaTeX
+
+## [2020-12-03]
+
+### Added
+- `\peek_analysis_map_inline:n`
+- `\peek_regex:nTF`, `\peek_regex_remove_once:nTF`, and
+  `\peek_regex_replace_once:nnTF`
+- `\token_case_catcode:NnTF`, `\token_case_charcode:NnTF`, and
+  `\token_case_meaning:NnTF`
+
+### Changed
+- Extend `\text_expand:n` to cover `\@protected at testopt`
+- Extend `\text_purify:n` to cover `\@protected at testopt`
+
+## [2020-10-27]
+
+### Added
+- `\token_if_font_selection:N(TF)` (see \#806)
+
+### Fixed
+- Avoid relying on braced `\input` primitive syntax
+- Correct expansion of environments in `\text_purify:n`
+- Some aspects of `cctab` setup with 8-bit engines(issue [\#814](https://github.com/latex3/latex3/issues/814))
+
+### Changed
+- Improved performance for `tl` functions
+- Extend case changer to cover all of Greek with pdfTeX
+
+## [2020-10-05]
+
+### Fixed
+- Correctly detect LaTeX when pre-loading expl3 and setting up
+  case changer
+- Lua emulation of \strcmp (issue [\#813](https://github.com/latex3/latex3/issues/813))
+
+## [2020-09-24]
+
+### Changed
+- Use Lua pseudo-primitives instead of `\directlua`
+- `\token_if_primitive:N(TF)` now reports pseudo-primitives as primitives in LuaTeX
+
+## [2020-09-06]
+
+### Fixed
+- Loading in generic mode (issue [\#800](https://github.com/latex3/latex3/issues/800))
+
+## [2020-09-03]
+
+### Fixed
+- Save primitive definition of `\pdfoutput` with CSLaTeX
+
+## [2020-09-01]
+
+### Added
+- `\hbox_overlap_center:n`
+
+### Changed
+- Backend setting for direct PDF output
+- Backend setting for XeTeX support
+
+### Deprecated
+- Backend setting `pdfmode`
+
+### Fixed
+- `\file_compare_timestamp:nNn(TF)` in LuaTeX (issue [\#792](https://github.com/latex3/latex3/issues/792))
+- Text case changing and expansion where an excluded command is equivalent
+  to `\use:n`
+
+## [2020-08-07]
+
+### Changed
+- Color selection implementation
+- Performance enhancements for `\keys_set:nn`
+
+### Fixed
+- Loading generically on ConTeXt (issue [\#783](https://github.com/latex3/latex3/issues/783))
+
+## [2020-07-17]
+
+### Added
+- `l3cctab` module for using category code tables
+- `\file_parse_full_name:n` and `\file_parse_full_name_apply:nN`
+- Additional `\prop_put:Nnn` variants
+- `\seq_set_map_x:NNn`
+- `\msg_term:nn(nnnn)`
+
+### Fixed
+- File lookup with `\input at path`
+- 8-bit encodings in `\str_set_convert:Nnnn`
+
+### Changed
+- Implementation of `\file_parse_full_name:nNNN` now uses
+  `\file_parse_full_name:n` internally
+- `\seq_set_map:NNn` no longer `x`-expands `<inline function>`
+  (`\seq_set_map_x:NNn` now does that).  Both moved to stable.
+
+### Removed
+- Functions deprecated at end of 2019
+
+### Deprecated
+- `\str_declare_eight_bit_encoding:nnn`
+
+## [2020-06-18]
+
+### Changed
+- Use `scn` operator for separations
+- Internal color model
+- Internal performance enhancements
+- Moved `\msg_expandable_error:nn(nnnn)` to stable.
+- Moved `\seq_indexed_map_inline:Nn` and `\seq_indexed_map_function:Nn`
+  to stable as `\seq_map_indexed_inline:Nn` and `\seq_map_indexed_function:Nn`.
+- Internal changes to `expl3` to allow loading earlier in LaTeX2e.
+
+## [2020-06-03]
+
+### Added
+- `\str_convert_pdfname:n`
+
+## [2020-05-15]
+
+### Changed
+- Make `\text_purify:n` `f`-type expandable
+
+## [2020-05-14]
+
+### Changed
+- Performance improvements in keyval processing
+
+## [2020-05-11]
+
+### Changed
+- Internal changes to quark handling
+
+## [2020-05-05]
+
+### Added
+- Recognize the exponent marker `E` (same as `e`) in floating point numbers
+
+### Fixed
+- Leave active characters untouched when case-changing (see \#715)
+
+## [2020-04-06]
+
+### Added
+- Control for start-of-titlecasing: see `\l_text_titlecase_check_letter_bool`
+
+### Fixed
+- Nesting of `\seq_shuffle:N` in another sequence mapping (issue [\#687](https://github.com/latex3/latex3/issues/687))
+- `\ior_shell_open:Nn` in engines other than LuaTeX - shell commands didn't
+  execute, plus the command call would be left in the input stream.
+
+## [2020-03-06]
+
+### Added
+- `\text_purify:n`
+
+### Fixed
+- Issue with case-changing Turkish
+
+## [2020-03-03]
+
+### Added
+- `\tex...:D` coverage for TeX Live 2020 engine changes
+
+### Changed
+- New implementation for `\keyval_parse:NNn` - around 40% speed improvement,
+  also *expandable*
+
+### Fixed
+- Make `expl3` reload-safe for `latexrelease` (see latex3/latex2e#295)
+
+## [2020-02-25]
+
+### Changed
+- Extend case-changing encoding support to Cyrillic and Greek
+
+## [2020-02-21]
+
+### Added
+- Option `suppress-backend-headers` (see matching change in
+  `l3backend`)
+
+### Changed
+- Allow `dvisvgm` driver with XeTeX (issue [\#677](https://github.com/latex3/latex3/issues/677))
+
+### Fixed
+- `undo-recent-deprecations` would not reload the deprecation code
+
+## [2020-02-14]
+
+### Fixed
+- Interaction with some `babel` languages at the start of the document
+
+## [2020-02-13]
+
+### Changed
+- Leave implicit tokens unchanged by `\text_expand:n`
+- Extend the `de-alt` case changing locale to 8-bit engines
+
+## [2020-02-11]
+
+### Added
+- Key property `.cs_set:Np` and variants
+
+### Changed
+- Support `\@uclclist` entries when case-changing
+
+### Fixed
+- Allow for full range of encodings when expanding text (issue [\#671](https://github.com/latex3/latex3/issues/671))
+- Support `\begin`/`\end` in text expansion
+
+## [2020-02-08]
+
+### Added
+- `\l_keys_key_str` and `\l_keys_path_str`
+
+### Deprecated
+- `\l_keys_key_tl` and `\l_keys_path_tl`, replaced by `\l_keys_key_str` and
+  `\l_keys_path_str`, respectively
+
+## [2020-02-03]
+
+### Changed
+- Minor edits to LaTeX3 News
+
+## [2020-01-31]
+
+### Added
+- Table of Contents for combined LaTeX3 News
+
+### Changed
+- Use Lua `utf8` library if available
+
+### Fixed
+- Undefined command in box debugging code
+
+## [2020-01-22]
+
+### Added
+- Support for command replacement in text expansion
+
+### Changed
+- Require key values for numerical key types (dim, int, etc.) (see \#661)
+
+### Fixed
+- Issue with keys where some leading spaces could be left in key names
+
+## [2020-01-12]
+
+### Added
+- `\bool_case_true:n(TF)` and `\bool_case_false:n(TF)`
+- `\file_hex_dump:n(nn)` and `\file_get_hex_dump:n(nn)N(TF)`
+- `\str_<type>case:n`
+- `\text_<type>case:n(n)`
+- `\text_expand:n` and supporting data structures
+
+### Changed
+- Distribute LaTeX3 News
+- Moved `\char_<type>case:N` to stable
+- Documentation improvements
+
+### Fixed
+- Inherit key required/forbidden properties (see \#653)
+- Set backend at the beginning of `\document` (see \#657)
+
+### Deprecated
+- `\str_<type>_case:n` replaced by `\str_<type>case:n`
+  except `\str_mixed_case:n` replaced by `\str_titlecase:n`
+- `\tl_<type>_case:n(n)` replaced by `\text_<type>case:n(n)`,
+  except `\tl_mixed_case:n(n)` replaced by `\text_titlecase:n(n)`
+
+## [2019-11-07]
+
+### Fixed
+- Handling of repeated loading of a backend (issue [\#646](https://github.com/latex3/latex3/issues/646))
+- Handling of repeated loading of deprecated functions
+
+## [2019-10-28]
+
+### Fixed
+- File searching when `\(pdf)filesize` is not available (issue \#644)
+
+## [2019-10-27]
+
+### Changed
+- Internal structure of `\c_sys_jobname_str` altered
+- Update upTeX test to follow guidance from developers
+
+## [2019-10-24]
+
+### Changed
+- File names are now returned without quotes by `\file_full_name:n`
+
+### Fixed
+- `\file_if_exist:n(TF)`, etc., when dealing with file names containing
+  spaces (see \#642)
+
+## [2019-10-21]
+
+### Added
+- Lua function `l3kernel.shellescape()`
+
+### Changed
+- Better coverage of (u)pTeX primitives following publication of
+  pTeX manual in English
+- Trim spaces surrounding file names
+
+### Removed
+- HarfTeX primitives
+
+## [2019-10-14]
+
+### Fixed
+- Correct handling of 'traditional' class options for backend
+
+## [2019-10-11]
+
+### Changed
+- Standard backend for (u)pTeX is now `dvips`
+- Minimum LuaTeX version now v0.95
+- Moved `\debug_on:n`, `\debug_off:n`, `\debug_suspend:` and `\debug_resume:`
+  to stable
+- Accept 'traditional' class options for backend (`dvipdfmx`, `dvips`, etc.)
+- Performance enhancements when loading `expl3`
+
+### Fixed
+- Handling of files with no extension
+- Behaviour of Lua function `l3kernel.charcat` in some circumstances
+- Loading under ConTeXt
+
+## [2019-10-02]
+
+### Fixed
+- Variants using `\exp_args` functions with more than 9 arguments (see \#636)
+
+## [2019-09-30]
+
+### Fixed
+- File searching using `\file_full_name:n` (see \#634)
+
+## [2019-09-28]
+
+### Changed
+- Speed up variants and reduce their `\tracingall` output
+- Debug and deprecation code are now loaded independently of expl3 core
+- `\file_compare_timestamp:nNn(TF)` now usable in expansion contexts
+- Moved to stable:
+  - `\bool_const:Nn`
+  - `\dim_sign:n`
+  - `\file_compare_timestamp:nNn(TF)`
+  - FP `logb` operator
+  - `\fp_sign:n`
+  - `fparray` module
+  - `\int_sign:n`
+  - `\intarray_const_from_clist:Nn`
+  - `\intarray_show:N`
+  - `\ior_map_variable:NNn`
+  - `\ior_str_map_variable:NNn`
+  - `\mode_leave_vertical:`
+  - `\prop_(g)set_from_clist:Nn`
+  - `\prop_const_from_clist:Nn`
+  - `\seq_const_from_clist:Nn`
+  - `\seq_(g)shuffle:N`
+  - `\sys_if_platform_unix:(TF)`
+  - `\sys_if_platform_windows:(TF)`
+  - `\sys_gset_rand_seed:`
+  - `\sys_rand_seed:`
+  - Shell access functions
+
+### Fixed
+- Key `.initial:n` property when combined with inherited keys (see \#631)
+
+## [2019-09-19]
+
+### Fixed
+- Loading Unicode data when some chars may be active (see \#627)
+
+## [2019-09-08]
+
+### Fixed
+- Missing internal variant (issue \#624)
+
+## [2019-09-05]
+
+### Added
+- `\file_full_name:n`, `\file_mdfive_hash:n`, `\file_size:n`,
+  `\file_timestamp:n`
+- `\seq_map_tokens:Nn`, `\tl_map_tokens:nn`, `\tl_map_tokens:Nn`
+
+### Changed
+- Moved `\prop_map_tokens:Nn` to stable
+- Generate chars with catcode as-supplied when case changing
+
+## [2019-08-25]
+
+### Added
+- `\fp_if_nan:nTF`
+
+### Changed
+- Make round(.,nan)=nan with no "Invalid operation" error
+
+### Fixed
+- `\tl_rescan:nn` and `\tl_(g)set_rescan:Nnn` when single-line input
+  contains a comment character (see \#607)
+- Final value of the variable in `\tl_map_variable:NNn` and
+  `\clist_map_variable:NNn`.
+- Remove duplicate keys in `\prop_set_from_keyval:Nn` (see \#572)
+
+## [2019-08-14]
+
+### Deprecated
+- `\c_term_ior`
+
+### Fixed
+- Coffin pole intersection in some cases (see \#605)
+
+## [2019-07-25]
+
+### Fixed
+- Loading for `expl3` with plain TeX
+
+## [2019-07-01]
+
+### Added
+- Moved `l3str-convert` module to `l3kernel`
+
+### Changed
+- Ensure `\msg_fatal:nn` ends the TeX run if used inside an
+  hbox (see \#587)
+- Moved backend code to a separate release schedule
+
+### Fixed
+- Handling of control sequences in key names (see \#594)
+
+## [2019-05-28]
+
+### Added
+- Experimental `\file_compare_timestamp:nNn(TF)`
+
+### Changed
+- Precedence of juxtaposition (implicit multiplication) in `l3fp`
+  now different for keywords/variables and factors in parentheses
+
+## [2019-05-09]
+
+### Added
+- Experimental driver-level interfaces for image inclusion
+- Experimental `\ior_shell_open:Nn`
+
+### Fixed
+- Some issues in `dvisvgm` driver
+
+## [2019-05-07]
+
+### Added
+- `.muskip_set:N` property
+
+### Changed
+- Experimental `\driver_pdf_compress_objects:n` replaces
+  `\driver_pdf_objects_(en|dis)able:`
+
+## [2019-05-05]
+
+### Added
+- `\char_str_<target>_case:N`
+
+### Fixed
+- Infinite loop in some cases in DVI mode due to link-breaking code
+  (see \#570)
+- Category code of output from `\char_<target>_case:N`, and
+  same issue in `\str_<target>_case:n`
+
+## [2019-05-03]
+
+### Added
+- New `l3legacy` module containing
+  - `\legacy_if:n(TF)`
+
+### Changed
+- Moved `\file_get_mdfive_hash:nN(TF)`, `\file_get_size:nN(TF)`
+   and `\file_get_timestamp:nN(TF)` to stable
+- Moved `\file_if_exist_input:n` and `\file_if_exist_input:nF` to stable
+- Moved `\file_input_stop:` to stable
+- Moved `\peek_N_type:TF` to stable
+
+## [2019-04-21]
+
+### Added
+- Experimental support for a range of PDF concepts at the lowest
+  (driver abstraction) level
+
+## [2019-04-06]
+
+### Changed
+- Moved `\tl_if_single_token:n(TF)` to stable
+
+### Fixed
+- Support for ConTeXt from mid-December 2018
+
+## [2019-03-26]
+
+### Fixed
+- Loading when pre-TL'18 XeTeX is in use (see \#555)
+
+## [2019-03-05]
+
+### Added
+- `\str_log:n`, `\str_log:N`
+- `TF` versions for `\file_get_...:nN` and `\ior_(str_)get:NN` functions
+- `\cs_prefix_spec:N`, `\cs_argument_spec:N`, `\cs_replacement_spec:N`
+- `undo-recent-deprecations` option
+- `factorial` function in `l3fp`
+
+### Changed
+- Return values from `\file_get:nnN`, `\file_get_...:nN`, `\ior_get:NN`,
+  `\sys_shell_get:nnN`
+- Moved coffin affine transformations to stable
+- Moved `\prop_count:N` to stable
+- Moved `\tl_count_tokens:n` to stable
+- Completed emulation of e-type argument when `\expanded` is unavailable
+- Made expandable messages expand their result, like usual messages
+- Made deprecation errors less intrusive by default
+- Stopped providing do-nothing `\color` macro when undefined
+
+### Deprecated
+- `\token_get_prefix_spec:N`, `\token_get_arg_spec:N`,
+  `\token_get_replacement_spec:N` replaced by `\cs_prefix_spec:N`,
+  `\cs_argument_spec:N`, `\cs_replacement_spec:N`, respectively
+
+### Fixed
+- Treatment of inherited keys when setting only known keys (see \#548)
+
+### Removed
+- Experimental `\skip_split_finite_else_action:nnNN`
+- Experimental `\tl_reverse_tokens:n`
+
+## [2019-02-15]
+
+### Changed
+- Defensive code for redefinition of `\time`, `\day`, `\month` and `\year`
+
+### Fixed
+- Resetting of key inheritance (see \#535)
+- Issue in deprecated command `\tl_set_from_file:Nnn`
+  (see https://tex.stackexchange.com/q/474813/)
+
+## [2019-02-03]
+
+### Added
+- Support for return of whole path by `\keys_set_known:nnN`-like
+  function `\keys_set_known:nnnN` (see \#508)
+- `.prop_(g)put:N` key property (see \#444)
+
+### Fixed
+- Handling of nested key setting when filtering, _etc._ (see \#526)
+- Inheritance of default values (see \#504)
+
+## [2019-01-28]
+
+### Added
+- Global versions of box affine functions, e.g. `\box_grotate:Nn`
+- Global versions of box size adjustment functions
+- `\box_(g)set_eq_drop:NN`, `\(h|v)box_unpack_drop:N`
+- `\file_get:nnN` and `\file_get:nnNTF`
+- Experimental functions `\sys_shell_get:nnN` and `\sys_shell_get:nnNTF`
+
+### Changed
+- `\char_generate:nn` now always takes exactly two expansions
+- Move `\prg_generate_conditional_variant:Nnn` to stable
+- Renamed experimental `\box_trim:Nnnnn` and `\box_viewport:Nnnnn` as
+  `\box_set_trim:Nnnnn` and `\box_set_viewport:Nnnnn`, respectively
+
+### Deprecated
+- `\box_(g)set_eq_clear:NN`, replaced by `\box_(g)set_eq_drop:NN`
+- `\(h|v)box_unpack_clear:N`, replaced by `\(h|v)box_unpack_drop:N`
+- `\tl_(g)set_from_file(_x):Nnn`, replaced by `\file_get:nnN`
+
+### Fixed
+- Scope treatment of `\box_set_dp:N`, _etc._
+- In (u)platex: detection of spaces in `\tl_rescan:nn` and related functions
+
+### Removed
+- Experimental function family `\tl_(g)set_from_shell:(N|c)nn`
+  (replaced by `\sys_shell_get:nnN`)
+
+## [2019-01-13]
+
+### Added
+- `\ior_map_variable:NNn` and `\ior_str_map_variable:NNn`
+
+### Fixed
+- Unclosed conditional with Unicode engines
+
+## [2019-01-12]
+
+### Changed
+- Improved `expl3` loading time with LuaTeX and XeTeX
+- Improved performance of `\ior_map_inline:Nn` and related functions
+
+### Fixed
+- Handling of accented characters under mixed case changing in 8-bit engines
+  (see \#514)
+
+## [2019-01-01]
+
+### Added
+- `\iow_allow_break:`
+
+### Fixed
+- Correct fp randint with zero argument (see \#507)
+- Handling of `\current at color` with `(x)dvipdfmx` (see \#510)
+
+### Removed
+- Support for stand-alone `l3regex`, `l3sort`, `l3srt`, `l3tl-analysis`,
+  `l3tl-build`
+- `\box_resize:Nnn`
+- `\box_use_clear:N`
+- `\c_minus_one`
+- `\file_add_path:nN`
+- `\file_list:`
+- `\file_path_include:n` and `\file_path_remove:n`
+- `\io(r|w)_list_streams:` and `\io(r|w)_log_streams:`
+- `\sort_ordered:` and `\sort_reversed:`
+- `\token_new:Nn`
+- Generation of invalid variants from `n`/`N` base types
+
+## [2018-12-12]
+
+### Changed
+- Move `\tl_range:nnn` to stable
+
+### Fixed
+- Loading in ConTeXt MkIV
+
+## [2018-12-11]
+
+### Changed
+- Enable `\char_generate:nn` to create active tokens with XeTeX
+
+## [2018-12-06]
+
+### Changed
+- Apply `\par` only at the end of vertical boxes
+- Move `\int_rand:n` to stable
+- Move `\<var>_rand_item:N` to stable
+
+### Fixed
+- Typo in `\lua_shipout_e:n` (see \#503)
+
+## [2018-11-19]
+
+### Added
+- Support for cross-compatibility primitives in XeTeX
+- `\int_sign:n`, `\dim_sign:n` and `\fp_sign:n`
+
+## [2018-10-19]
+
+### Fixed
+- Wrapping of text in messages, etc., for some line lengths (issue \#491)
+
+## [2018-10-17]
+
+### Added
+- `\g_msg_module_documentation_prop` (see \#471)
+- `\peek_remove_spaces:n`
+
+### Changed
+- Formatting of messages: now follows LaTeX2e closely
+
+### Deprecated
+- `\msg_interrupt:nn`, `\msg_log:n` and `\msg_term:n`
+
+### Fixed
+- Handling of inheritance for choice keys (issue \#483)
+
+## [2018-09-24]
+
+### Added
+- Some driver-level support for PDF features
+- `\peek_catcode_collect_inline:Nn`, `\peek_charcode_collect_inline:Nn`,
+  `\peek_meaning_collect_inline:Nn`
+
+### Fixed
+- Handling of unknown keys when inheritance is active (issue \#481)
+
+## [2018-08-23]
+
+### Added
+- `\lua_escape:e`, `\lua_now:e` and `\lua_shipout_e:n`
+- `\str_case_e:nn(TF)` and `\str_if_eq:ee(TF)`
+- `\sys_if_platform_unix:(TF)` and `\sys_if_platform_windows:(TF)`
+- `\tl_(g)set_from_shell:Nnn`
+
+### Deprecated
+- `\lua_escape_x:n`, `\lua_now_x:n` and `\lua_shipout_x:n`
+- `\str_case_x:nn(TF)` and `\str_if_eq_x:nn(TF)`
+
+## [2018-06-14]
+
+### Added
+- Support for `e`-type argument using `\expanded` or macro emulation
+
+## [2018-06-01]
+
+### Added
+- `CHANGELOG.md` (issue \#460)
+
+### Fixed
+- Loading `expl3` with LuaTeX/XeTeX and certain letter tokens set
+  to be active (see \#462)
+
+### Changed
+- Alter `\char_codepoint_from_bytes:n` to produce four groups in all
+  cases; make `f`-type expandable
+
+## [2018-05-13]
+
+### Fixed
+- Correct date string in `expl3.dtx`
+- Correct `\c_sys_engine_version_str` when using XeTeX
+
+## [2018-05-12]
+
+### Added
+- Define `\c_zero_int` and `\c_one_int`
+- Implement `\c_sys_engine_version_str`
+- Implement `\seq_indexed_map_function/inline`
+- Implement `\intarray_gzero:N`
+- Implement `\intarray_const_from_clist:Nn`
+- Implement `\bool_set_inverse:N`
+- Implement `\bool_xor:nnTF` instead of just `\bool_xor_p:nn`
+- Implement candidate `\int_rand:n`
+- Implement `\intarray_gset_rand:Nnn`
+- Implement candidate `l3fparray` module
+
+### Changed
+- Update minimal required versions of XeTeX and LuaTeX
+- Deprecate named integer constants `\c_zero`. etc.
+- Move all primitives to `\tex_...:D namespace`,
+  deprecating older engine-dependent prefixes
+- Several internal optimisations
+
+### Fixed
+- Expand boolean expression before calling `\chardef` (issue \#461)
+
+### Removed
+- Remove undocumented `\fp_function:Nw` and `\fp_new_function:Npn`
+
+## [2018-04-30]
+
+### Added
+- Implement `\tl_analysis_map_inline:nn`
+- Implement `\exp_args_generate:n` to define new `\exp_args:N...`
+  functions
+- Low-level `\int_value:w` function
+- New experimental functions for
+  - Building token lists piecewise
+  - Fast manipulation of integer arrays
+  - Sequence shuffling
+  - `\seq_set_from_function:NnN`
+  - `\char_codepoint_to_bytes:n`
+
+### Changed
+- Significant internal revision to use only internal functions
+  'private' to specific modules
+- Better documentation of cross-module kernel-internal functions
+- Enable `\char_generate:nn` for active chars
+- Renamed `\tl_show_analysis:(N|n)n` as `\tl_analysis_show:(N|n)n`
+- Change `\int_rand:nn` (and rand_item functions) to better use
+  the RNG
+- Make prg break functions public
+- Make scan marks mechanism public
+- Make `\prg_do_nothing:` long rather than nopar (issue \#455)
+- Several performance improvements
+- Documentation improvements
+
+### Fixed
+- Only index TF, T, F functions together if they are `expl3`
+  functions (issue \#453)
+- Make `\infty` and `\pi` into errors in fp expressions
+  (issue \#357)
+
+### Removed
+- Deprecated functions expiring at end of 2017
+- Old module `.sty` files
+
+## [2018-03-05]
+
+### Changes
+- Adjustments to `l3drivers` to support `l3draw` development in
+  `l3experimental` bundle
+
+## [2018-02-21]
+
+### Added
+- Tuple support in fp expressions
+- Step functions have been added for dim variables,
+  e.g. `\dim_step_inline:nnnn`
+
+[Unreleased]: https://github.com/latex3/latex3/compare/2024-04-11...HEAD
+[2024-04-11]: https://github.com/latex3/latex3/compare/2024-03-14...2024-04-11
+[2024-03-14]: https://github.com/latex3/latex3/compare/2024-02-20...2024-03-14
+[2024-02-20]: https://github.com/latex3/latex3/compare/2024-02-18...2024-02-20
+[2024-02-18]: https://github.com/latex3/latex3/compare/2024-02-13...2024-02-18
+[2024-02-13]: https://github.com/latex3/latex3/compare/2024-01-22...2024-02-13
+[2024-01-22]: https://github.com/latex3/latex3/compare/2024-01-04...2024-01-22
+[2024-01-04]: https://github.com/latex3/latex3/compare/2023-12-11...2024-01-04
+[2023-12-11]: https://github.com/latex3/latex3/compare/2023-12-08...2023-12-11
+[2023-12-08]: https://github.com/latex3/latex3/compare/2023-11-09...2023-12-08
+[2023-11-09]: https://github.com/latex3/latex3/compare/2023-11-01...2023-11-09
+[2023-11-01]: https://github.com/latex3/latex3/compare/2023-10-23...2023-11-01
+[2023-10-23]: https://github.com/latex3/latex3/compare/2023-10-10...2023-10-23
+[2023-10-10]: https://github.com/latex3/latex3/compare/2023-08-29...2023-10-10
+[2023-08-29]: https://github.com/latex3/latex3/compare/2023-08-11...2023-08-29
+[2023-08-11]: https://github.com/latex3/latex3/compare/2023-08-03...2023-08-11
+[2023-08-03]: https://github.com/latex3/latex3/compare/2023-06-30...2023-08-03
+[2023-06-30]: https://github.com/latex3/latex3/compare/2023-06-16...2023-06-30
+[2023-06-16]: https://github.com/latex3/latex3/compare/2023-06-05...2023-06-16
+[2023-06-05]: https://github.com/latex3/latex3/compare/2023-05-22...2023-06-05
+[2023-05-22]: https://github.com/latex3/latex3/compare/2023-05-15...2023-05-22
+[2023-05-15]: https://github.com/latex3/latex3/compare/2023-05-11...2023-05-15
+[2023-05-11]: https://github.com/latex3/latex3/compare/2023-05-05...2023-05-11
+[2023-05-05]: https://github.com/latex3/latex3/compare/2023-04-20...2023-05-05
+[2023-04-20]: https://github.com/latex3/latex3/compare/2023-04-19...2023-04-20
+[2023-04-19]: https://github.com/latex3/latex3/compare/2023-03-30...2023-04-19
+[2023-03-30]: https://github.com/latex3/latex3/compare/2023-02-22...2023-03-30
+[2023-02-22]: https://github.com/latex3/latex3/compare/2023-02-07...2023-02-22
+[2023-02-07]: https://github.com/latex3/latex3/compare/2023-02-02...2023-02-07
+[2023-02-02]: https://github.com/latex3/latex3/compare/2023-02-01...2023-02-02
+[2023-02-01]: https://github.com/latex3/latex3/compare/2023-01-24...2023-02-01
+[2023-01-24]: https://github.com/latex3/latex3/compare/2023-01-16...2023-01-24
+[2023-01-16]: https://github.com/latex3/latex3/compare/2022-12-17...2023-01-16
+[2022-12-17]: https://github.com/latex3/latex3/compare/2022-11-02...2022-12-17
+[2022-11-02]: https://github.com/latex3/latex3/compare/2022-10-26...2022-11-02
+[2022-10-26]: https://github.com/latex3/latex3/compare/2022-09-28...2022-10-26
+[2022-09-28]: https://github.com/latex3/latex3/compare/2022-08-30...2022-09-28
+[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
+[2022-07-14]: https://github.com/latex3/latex3/compare/2022-07-04...2022-07-14
+[2022-07-04]: https://github.com/latex3/latex3/compare/2022-07-01...2022-07-04
+[2022-07-01]: https://github.com/latex3/latex3/compare/2022-06-16...2022-07-01
+[2022-06-16]: https://github.com/latex3/latex3/compare/2022-06-02...2022-06-16
+[2022-06-02]: https://github.com/latex3/latex3/compare/2022-05-30...2022-06-02
+[2022-05-30]: https://github.com/latex3/latex3/compare/2022-05-04...2022-05-30
+[2022-05-04]: https://github.com/latex3/latex3/compare/2022-04-29...2022-05-04
+[2022-04-29]: https://github.com/latex3/latex3/compare/2022-04-20...2022-04-29
+[2022-04-20]: https://github.com/latex3/latex3/compare/2022-04-10...2022-04-20
+[2022-04-10]: https://github.com/latex3/latex3/compare/2022-02-24...2022-04-10
+[2022-02-24]: https://github.com/latex3/latex3/compare/2022-02-21...2022-02-24
+[2022-02-21]: https://github.com/latex3/latex3/compare/2022-02-05...2022-02-21
+[2022-02-05]: https://github.com/latex3/latex3/compare/2022-01-21...2022-02-05
+[2022-01-21]: https://github.com/latex3/latex3/compare/2022-01-12...2022-01-21
+[2022-01-12]: https://github.com/latex3/latex3/compare/2021-11-22...2022-01-12
+[2021-11-22]: https://github.com/latex3/latex3/compare/2021-11-12...2021-11-22
+[2021-11-12]: https://github.com/latex3/latex3/compare/2021-10-18...2021-11-12
+[2021-10-18]: https://github.com/latex3/latex3/compare/2021-10-17...2021-10-18
+[2021-10-17]: https://github.com/latex3/latex3/compare/2021-10-12...2021-10-17
+[2021-10-12]: https://github.com/latex3/latex3/compare/2021-08-27...2021-10-12
+[2021-08-27]: https://github.com/latex3/latex3/compare/2021-07-12...2021-08-27
+[2021-07-12]: https://github.com/latex3/latex3/compare/2021-06-18...2021-07-12
+[2021-06-18]: https://github.com/latex3/latex3/compare/2021-06-01...2021-06-18
+[2021-06-01]: https://github.com/latex3/latex3/compare/2021-05-27...2021-06-01
+[2021-05-27]: https://github.com/latex3/latex3/compare/2021-05-25...2021-05-27
+[2021-05-25]: https://github.com/latex3/latex3/compare/2021-05-11...2021-05-25
+[2021-05-11]: https://github.com/latex3/latex3/compare/2021-05-07...2021-05-11
+[2021-05-07]: https://github.com/latex3/latex3/compare/2021-02-18...2021-05-07
+[2021-02-18]: https://github.com/latex3/latex3/compare/2021-02-06...2021-02-18
+[2021-02-06]: https://github.com/latex3/latex3/compare/2021-02-02...2021-02-06
+[2021-02-02]: https://github.com/latex3/latex3/compare/2021-01-09...2021-02-02
+[2021-01-09]: https://github.com/latex3/latex3/compare/2020-12-07...2021-01-09
+[2020-12-07]: https://github.com/latex3/latex3/compare/2020-12-05...2020-12-07
+[2020-12-05]: https://github.com/latex3/latex3/compare/2020-12-03...2020-12-05
+[2020-12-03]: https://github.com/latex3/latex3/compare/2020-10-27...2020-12-03
+[2020-10-27]: https://github.com/latex3/latex3/compare/2020-10-05...2020-10-27
+[2020-10-05]: https://github.com/latex3/latex3/compare/2020-09-24...2020-10-05
+[2020-09-24]: https://github.com/latex3/latex3/compare/2020-09-06...2020-09-24
+[2020-09-06]: https://github.com/latex3/latex3/compare/2020-09-03...2020-09-06
+[2020-09-03]: https://github.com/latex3/latex3/compare/2020-09-01...2020-09-03
+[2020-09-01]: https://github.com/latex3/latex3/compare/2020-08-07...2020-09-01
+[2020-08-07]: https://github.com/latex3/latex3/compare/2020-07-17...2020-08-07
+[2020-07-17]: https://github.com/latex3/latex3/compare/2020-06-18...2020-07-17
+[2020-06-18]: https://github.com/latex3/latex3/compare/2020-06-03...2020-06-18
+[2020-06-03]: https://github.com/latex3/latex3/compare/2020-05-15...2020-06-03
+[2020-05-15]: https://github.com/latex3/latex3/compare/2020-05-14...2020-05-15
+[2020-05-14]: https://github.com/latex3/latex3/compare/2020-05-11...2020-05-14
+[2020-05-11]: https://github.com/latex3/latex3/compare/2020-05-05...2020-05-11
+[2020-05-05]: https://github.com/latex3/latex3/compare/2020-04-06...2020-05-05
+[2020-04-06]: https://github.com/latex3/latex3/compare/2020-03-06...2020-04-06
+[2020-03-06]: https://github.com/latex3/latex3/compare/2020-03-03...2020-03-06
+[2020-03-03]: https://github.com/latex3/latex3/compare/2020-02-25...2020-03-03
+[2020-02-25]: https://github.com/latex3/latex3/compare/2020-02-21...2020-02-25
+[2020-02-21]: https://github.com/latex3/latex3/compare/2020-02-14...2020-02-21
+[2020-02-14]: https://github.com/latex3/latex3/compare/2020-02-13...2020-02-14
+[2020-02-13]: https://github.com/latex3/latex3/compare/2020-02-11...2020-02-13
+[2020-02-11]: https://github.com/latex3/latex3/compare/2020-02-08...2020-02-11
+[2020-02-08]: https://github.com/latex3/latex3/compare/2020-02-03...2020-02-08
+[2020-02-03]: https://github.com/latex3/latex3/compare/2020-01-31...2020-02-03
+[2020-01-31]: https://github.com/latex3/latex3/compare/2020-01-22...2020-01-31
+[2020-01-22]: https://github.com/latex3/latex3/compare/2020-01-12...2020-01-22
+[2020-01-12]: https://github.com/latex3/latex3/compare/2019-11-07...2020-01-12
+[2019-11-07]: https://github.com/latex3/latex3/compare/2019-10-28...2019-11-07
+[2019-10-28]: https://github.com/latex3/latex3/compare/2019-10-27...2019-10-28
+[2019-10-27]: https://github.com/latex3/latex3/compare/2019-10-24...2019-10-27
+[2019-10-24]: https://github.com/latex3/latex3/compare/2019-10-21...2019-10-24
+[2019-10-21]: https://github.com/latex3/latex3/compare/2019-10-14...2019-10-21
+[2019-10-14]: https://github.com/latex3/latex3/compare/2019-10-11...2019-10-14
+[2019-10-11]: https://github.com/latex3/latex3/compare/2019-10-02...2019-10-11
+[2019-10-02]: https://github.com/latex3/latex3/compare/2019-09-30...2019-10-02
+[2019-09-30]: https://github.com/latex3/latex3/compare/2019-09-28...2019-09-30
+[2019-09-28]: https://github.com/latex3/latex3/compare/2019-09-19...2019-09-28
+[2019-09-19]: https://github.com/latex3/latex3/compare/2019-09-08...2019-09-19
+[2019-09-08]: https://github.com/latex3/latex3/compare/2019-09-05...2019-09-08
+[2019-09-05]: https://github.com/latex3/latex3/compare/2019-08-25...2019-09-05
+[2019-08-25]: https://github.com/latex3/latex3/compare/2019-08-14...2019-08-25
+[2019-08-14]: https://github.com/latex3/latex3/compare/2019-07-25...2019-08-14
+[2019-07-25]: https://github.com/latex3/latex3/compare/2019-07-01...2019-07-25
+[2019-07-01]: https://github.com/latex3/latex3/compare/2019-05-28...2019-07-01
+[2019-05-28]: https://github.com/latex3/latex3/compare/2019-05-09...2019-05-28
+[2019-05-09]: https://github.com/latex3/latex3/compare/2019-05-07...2019-05-09
+[2019-05-07]: https://github.com/latex3/latex3/compare/2019-05-05...2019-05-07
+[2019-05-05]: https://github.com/latex3/latex3/compare/2019-05-03...2019-05-05
+[2019-05-03]: https://github.com/latex3/latex3/compare/2019-04-21...2019-05-03
+[2019-04-21]: https://github.com/latex3/latex3/compare/2019-04-06...2019-04-21
+[2019-04-06]: https://github.com/latex3/latex3/compare/2019-03-26...2019-04-06
+[2019-03-26]: https://github.com/latex3/latex3/compare/2019-03-05...2019-03-26
+[2019-03-05]: https://github.com/latex3/latex3/compare/2019-02-15...2019-03-05
+[2019-02-15]: https://github.com/latex3/latex3/compare/2019-02-03...2019-02-15
+[2019-02-03]: https://github.com/latex3/latex3/compare/2019-01-28...2019-02-03
+[2019-01-28]: https://github.com/latex3/latex3/compare/2019-01-13...2019-01-28
+[2019-01-13]: https://github.com/latex3/latex3/compare/2019-01-12...2019-01-13
+[2019-01-12]: https://github.com/latex3/latex3/compare/2019-01-01...2019-01-12
+[2019-01-01]: https://github.com/latex3/latex3/compare/2018-12-12...2019-01-01
+[2018-12-12]: https://github.com/latex3/latex3/compare/2018-12-11...2018-12-12
+[2018-12-11]: https://github.com/latex3/latex3/compare/2018-12-06...2018-12-11
+[2018-12-06]: https://github.com/latex3/latex3/compare/2018-11-19...2018-12-06
+[2018-11-19]: https://github.com/latex3/latex3/compare/2018-10-31...2018-11-19
+[2018-10-31]: https://github.com/latex3/latex3/compare/2018-10-26...2018-10-31
+[2018-10-26]: https://github.com/latex3/latex3/compare/2018-10-19...2018-10-26
+[2018-10-19]: https://github.com/latex3/latex3/compare/2018-10-17...2018-10-19
+[2018-10-17]: https://github.com/latex3/latex3/compare/2018-09-24...2018-10-17
+[2018-09-24]: https://github.com/latex3/latex3/compare/2018-08-23...2018-09-24
+[2018-08-23]: https://github.com/latex3/latex3/compare/2018-06-14...2018-08-23
+[2018-06-14]: https://github.com/latex3/latex3/compare/2018-06-01...2018-06-14
+[2018-06-01]: https://github.com/latex3/latex3/compare/2018-05-13...2018-06-01
+[2018-05-13]: https://github.com/latex3/latex3/compare/2018-05-12...2018-05-13
+[2018-05-12]: https://github.com/latex3/latex3/compare/2018-04-30...2018-05-12
+[2018-04-30]: https://github.com/latex3/latex3/compare/2018-03-05...2018-04-30
+[2018-03-05]: https://github.com/latex3/latex3/compare/2018-02-21...2018-03-05
+[2018-02-21]: https://github.com/latex3/latex3/compare/2017-12-16...2018-02-21


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/CHANGELOG.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/README.md	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,96 @@
+LaTeX3 Programming Conventions
+==============================
+
+Release 2024-04-11
+
+Overview
+--------
+
+The files of the `l3kernel` bundle provide an API for TeX programmers
+with defined syntax conventions, completely separating it from document level
+syntax. Hence, the commands provided are not intended for use at the document
+level nor for use in describing design layouts in document class files.
+
+This API provides the foundation on which new additions to the LaTeX kernel and
+other advanced extensions are built. The programming layer is designed to be
+loaded as part of LaTeX2e format building or as a loaded package with plain TeX
+or other formats.
+
+The syntax and functionality provided by `l3kernel` is regarded by the LaTeX
+team as stable. There may still be changes to some functions, but these will be
+very minor when compared to the scope of `l3kernel`. In particular, no functions
+will be removed, although some may be deprecated.
+
+
+Requirements
+------------
+
+The `l3kernel` bundle requires the e-TeX extensions and a number of additional
+'utility' primitives, almost all of which were first added to pdfTeX. In
+particular, the functionality equivalent to the following pdfTeX primitives must
+be available
+
+- `\ifincsname`
+- `\ifpdfprimitive`
+- `\pdfcreationdate`
+- `\pdfelapsedtime`
+- `\pdffiledump`
+- `\pdffilemoddate`
+- `\pdffilesize`
+- `\pdflastxpos`
+- `\pdflastypos`
+- `\pdfmdfivesum`
+- `\pdfnormaldeviate`
+- `\pdfpageheight`
+- `\pdfpagewidth`
+- `\pdfprimitive`
+- `\pdfrandomseed`
+- `\pdfresettimer`
+- `\pdfsavepos`
+- `\pdfsetrandomseed`
+- `\pdfshellescape`
+- `\pdfstrcmp`
+- `\pdfuniformdeviate`
+
+For ease of reference, these primitives will be referred to as the 'pdfTeX
+utilities'. With the exception of `\expanded`, these have been present in pdfTeX
+since the release of version 1.40.0 in 2007; `\expanded` was added for TeX Live
+2019. Similarly, the full set of these utility primitives has been available in
+XeTeX from the 2019 TeX Live release, and has always been available in LuaTeX
+(some by Lua emulation). The Japanese pTeX and upTeX gained all of the above
+(except `\ifincsname`) for TeX Live 2019 and `\ifincsname` for TeX Live 2020.
+
+Starting from release 2023-05-15, the `\expanded` primitive is *required*.
+Its slow emulation has been removed.
+
+In addition to the above, engines which are fully Unicode-compatible
+must provide the functionality of the following primitives, documented in the
+LuaTeX manual
+
+- `\Uchar`
+- `\Ucharcat`
+- `\Umathcode`
+
+The existence of the primitive `\Umathcode` is used as the marker for Unicode
+support.
+
+Issues
+------
+
+The issue tracker for LaTeX3 is currently located
+[on GitHub](https://github.com/latex3/latex3/issues).
+
+The LaTeX Project
+------------------
+
+Development of LaTeX3 is carried out by
+[The LaTeX Project](https://www.latex-project.org/latex3/).
+
+The development team can be contacted
+by e-mail: <latex-team at latex-project.org>.
+
+-----
+
+<p>Copyright (C) 1998-2012,2015-2024 The LaTeX Project <br />
+<a href="http://latex-project.org/">http://latex-project.org/</a> <br />
+All rights reserved.</p>


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/expl3.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/expl3.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/expl3.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/expl3.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/expl3.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,82 @@
+\iffalse meta-comment
+
+File: interface3.tex
+
+Copyright (C) 1990-2011,2017-2024 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 released version of this bundle is available from CTAN.
+
+-----------------------------------------------------------------------
+
+The development version of the bundle can be found at
+
+   https://github.com/latex3/latex3
+
+for those people who are interested.
+
+\fi
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% This document typesets the LaTeX3 interface descriptions a single document.
+% This produces quite a large file (more than 360 pages as of Dec 2023).
+%
+% There is also a full version of the sources (source3.tex) which additionally
+% also typesets the command implementations.
+%
+% Do not forget to generate the index (as explained on the terminal output
+% near the end of the run)!
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+\documentclass[kernel]{l3doc}
+
+\newif\ifinterface
+\interfacetrue
+
+\listfiles
+
+\begin{document}
+
+\title{The \LaTeX3 Interfaces}
+\author{%
+ The \LaTeX{} Project\thanks
+   {%
+     E-mail:
+       \href{mailto:latex-team at latex-project.org}
+         {latex-team at latex-project.org}%
+   }%
+}
+\date{Released 2024-04-11}
+
+\pagenumbering{roman}
+\maketitle
+
+%
+% First load all modules and typeset the documentation parts
+%
+
+\input{source3body}    % all the individual modules
+
+\clearpage
+
+\begingroup
+  \def\endash{--}
+  \catcode`\-\active
+  \def-{\futurelet\temp\indexdash}
+  \def\indexdash{\ifx\temp-\endash\fi}
+  \DelayPrintIndex
+\endgroup
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/interface3.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3doc.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3doc.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3doc.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3doc.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3doc.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3docstrip.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3docstrip.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3docstrip.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3docstrip.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3docstrip.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,187 @@
+% Copyright 2019-2021 The LaTeX Project
+
+\providecommand*{\lastissue}{12}
+
+\documentclass{ltnews}
+
+\AtBeginDocument{%
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}%
+  \RaggedRight
+  \setlength\parindent{1em}%
+}
+\usepackage{catchfile}
+\usepackage{csquotes}
+\usepackage{enumitem}
+\usepackage{fancyvrb}
+\usepackage{hologo}
+\usepackage{metalogo}
+\usepackage{multicol}
+\usepackage{ragged2e}
+\usepackage{siunitx}
+\usepackage{tikz}
+\usepackage{underscore}
+\usepackage{xparse}
+\usepackage{hyperref}
+\hypersetup{colorlinks}
+\usepackage{bookmark}
+
+\MakeOuterQuote{"}
+
+\pdfstringdefDisableCommands
+  {%
+    \RenewExpandableDocumentCommand \cs { O{} m }
+      {\textbackslash#2}%
+  }
+
+\makeatletter
+\newcounter{issue}
+\renewcommand*{\theissue}{%
+  \ifnum\value{issue}<10 0\fi
+  \number\value{issue}%
+}
+\newcommand*{\MonthJanuary}{01}
+\newcommand*{\MonthFebruary}{02}
+\newcommand*{\MonthMarch}{03}
+\newcommand*{\MonthApril}{04}
+\newcommand*{\MonthMay}{05}
+\newcommand*{\MonthJune}{06}
+\newcommand*{\MonthJuly}{07}
+\newcommand*{\MonthAugust}{08}
+\newcommand*{\MonthSeptember}{09}
+\newcommand*{\MonthOctober}{10}
+\newcommand*{\MonthNovember}{11}
+\newcommand*{\MonthDecember}{12}
+\newcommand*{\printissue}{%
+  Issue %
+  \texorpdfstring{\number\value{issue}}{\theissue}, %
+  \texorpdfstring{\@month\space\@year}{\@year/\@nameuse{Month\@month}}%
+}
+\let\l at part\l at section
+\let\l at section\l at subsection
+\let\l at subsection\l at subsubsection
+\let\l at subsubsection\l at paragraph
+\let\l at paragraph\l at subparagraph
+\newcommand*{\makefirsttitle}{%
+  \twocolumn[{%
+    \parbox[t][4\baselineskip]{\textwidth}{%
+      \@titlefont\@title, Issues 1--\lastissue
+    }%
+  }]%
+}
+
+% show the page number on first page of issues:
+
+\renewcommand{\ps at titlepage}{%
+   \renewcommand{\@oddhead}{\hfill}%
+   \renewcommand{\@evenhead}{\hfill}%
+   \renewcommand{\@oddfoot}{\@indiciafont\@indicia\hfill --\thepage}%
+   \renewcommand{\@evenfoot}{\@indiciafont\@indicia\hfill --\thepage}%
+}
+
+% only needed if the old ltnews class is used
+\renewcommand{\@oddfoot}{\@indiciafont\mbox{}\hfill --\thepage}%
+\renewcommand{\@evenfoot}{\@indiciafont\mbox{}\hfill --\thepage}%
+
+
+\makeatother
+
+\begin{document}
+
+%%% Title and Table of Contents
+
+\makefirsttitle
+\pdfbookmark[0]{\contentsname}{toc}
+\tableofcontents
+\clearpage
+
+\begingroup
+  \renewcommand*{\AtBeginDocument}[1]{#1}%
+  \renewcommand*{\PassOptionsToPackage}[2]{}%
+  \renewcommand*{\usepackage}[2][]{}%
+  \renewcommand*{\RequirePackage}[2][]{}%
+  \renewcommand*{\documentclass}[2][]{%
+    \setcounter{footnote}{0}%
+    \gobbleopt
+  }%
+  \newcommand*{\gobbleopt}[1][]{}%
+  \makeatletter
+  \let\org at twocolumn\twocolumn
+  \renewenvironment{document}{%
+    \clearpage
+    \ifnum\@issue=20 %
+      \addtocontents{toc}{\protect\setcounter{tocdepth}{5}}%
+      \addtocontents{toc}{%
+        \protect\makeatletter
+       }%
+       \addtocontents{toc}{%
+         \let\protect\saved at l@paragraph\protect\l at paragraph
+       }%
+       \addtocontents{toc}{%
+         \let\protect\l at paragraph\protect\l at subsection
+       }%
+    \fi
+    \ifnum\@issue>9\space  % we may have issue tocs ...
+      \addtocontents{toc}{%
+        \let\protect\l at paragraph\protect\saved at l@paragraph
+      }%
+      \def\toclevel at subsection{1}%
+      \def\toclevel at subsubsection{2}%
+      \addtocontents{toc}{\protect\setcounter{tocdepth}{4}}%
+      \renewcommand*{\tableofcontents}{%
+        \section*{\contentsname}%
+        \@starttoc{toc\theissue}%
+      }%
+      \let\saved at addtocontents\addtocontents
+      \renewcommand*{\addtocontents}[2]{%
+        \saved at addtocontents{##1}{##2}%
+        \def\temp at toc{toc}%
+        \def\temp at param{##1}%
+        \ifx\temp at toc\temp at param
+          \saved at addtocontents{toc\theissue}{##2}%
+        \fi
+      }%
+      \let\l at subsubsection\l at subsection
+      \let\l at subsection\l at section
+      \let\l at section\l at part
+      \let\l at part\@gobbletwo
+    \fi
+    \def\twocolumn[{%
+      \let\twocolumn\org at twocolumn
+      \org at twocolumn[%
+      {% because of optional argument of \twocolumn
+        \pdfbookmark[0]{\printissue}{issue\theissue}%
+      }%
+      \begingroup
+        \let\WriteBookmarks\relax
+        \@firstofone{% inside opt. arg. of \twocolumn: protect "]"
+          \renewcommand*{\Hy at writebookmark}[5]{}%
+        }%
+        \phantomsection
+        \addcontentsline{toc}{part}{\printissue}%
+      \endgroup
+    }%
+  }{%
+    \clearpage
+  }%
+  \def\MakeOuterQuote#1{%
+    \if\noexpand"\noexpand#1%
+    \else
+      \@latex at error{Unexpected \string\MakeOuterQuote
+          {\detokenize{#1}}\MessageBreak%
+        Check if output is valid in `l3news\theissue.tex'}%
+    \fi}
+  \makeatother
+  \loop
+  \ifnum\value{issue}<\lastissue
+    \stepcounter{issue}%
+    \input{l3news\theissue}%
+  \repeat
+  \stepcounter{issue}%
+  \IfFileExists{l3news\theissue}{%
+    \@latex at error{\jobname.tex is out of date,\MessageBreak
+      there is `l3news\theissue.tex'%
+    }\@ehc
+  }{}%
+\endgroup
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,102 @@
+% Copyright 2009 The LaTeX Project
+\documentclass{ltnews}
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+}
+
+\publicationmonth{February}
+\publicationyear{2009}
+\publicationissue{1}
+
+\begin{document}
+\maketitle
+
+\section{Welcome to \LaTeX3}
+
+Momentum is again starting to build behind The \LaTeX{} Project. For the
+last few releases of \TeX~Live, the experimental programming foundation for
+\LaTeX3 has been available under the name \package{expl3}. Despite large
+warnings that the code would probably change in the future, we wanted to show
+that there was progress being made, no matter how slowly. Since then, some
+people have looked at the code, provided feedback, and~--- most
+importantly~--- actually tried using it. Although it is yet early days, we
+believe that the ideas behind the code are sound and there are only `cosmetic
+improvements' that need to be made before \package{expl3} is ready for the
+\LaTeX~package author masses.
+
+\section{What currently exists}
+
+The current \LaTeX3 code consists of two main branches: the
+\package{expl3} modules that define the underlying programming environment,
+and the `\package{xpackage}s', which are a suite of packages that are written
+with the \package{expl3} programming interface and provide some higher-level
+functionality for what will one day become \LaTeX3 proper. Both \package{expl3} and
+parts of the \package{xpackages} are designed to be used \emph{on top} of
+\LaTeXe, so new packages can take advantage of the new features while still
+allowing to be used alongside many of the vast number of \LaTeXe\ packages on
+\textsc{ctan}.
+
+\section{What's happening now}
+
+In preparation for a minor overhaul of the \package{expl3} code, we are
+writing a comprehensive test suite for each module. These tests allow us to
+make implementation changes and then test if the code still works as before.
+They are also highlighting any minor shortcomings or omissions in the code.
+As the tests are being written, our assumptions about what should be called
+what and the underlying naming conventions for the functions and datatypes are
+being questioned, challenged, and noted for further rumination.
+
+At the time of writing, we are approximately half-way through writing the test
+suite. Once this task is complete, which we plan for the first
+half of 2009, we will be ready to make changes without worrying about breaking
+anything.
+
+\section{What's happening soon}
+
+So what do we want to change? The current \package{expl3} codebase has
+portions that date to the pre-\LaTeXe\ days, while other modules have been
+more recently conceived. It is quite apparent when reading through the sources
+that some unification and tidying up would improve the simplicity and
+consistency of the code. In many cases, such changes will mean nothing more
+than a tweak or a rename.
+
+Beyond these minor changes, we are also re-thinking the exact notation behind
+the way functions are defined. There are currently a handful of different
+types of arguments that functions may be passed (from an untouched single
+token to a complete expansion of a token list) and we're not entirely happy
+with how the original choices have evolved now that the system has grown
+somewhat. We have received good feedback from several people on ways that we
+could improve the argument syntax, and as part of the upcoming changes to the
+\package{expl3} packages we hope to address the problems that we currently
+perceive in the present syntax.
+
+\section{What's happening later}
+
+After the changes discussed above are finished, we will begin freezing the core
+interface of the \package{expl3} modules, and we hope that more package
+authors will be interested in using the new ideas to write their own code.
+While the core functions will then remain unchanged, more features and new
+modules will be added as \LaTeX3 starts to grow.
+
+Some new and/or experimental packages will be changing to use the
+\package{expl3} programming interface, including \package{breqn},
+\package{mathtools}, \package{empheq}, \package{fontspec}, and
+\package{unicode-math}. (Which is one reason for the lack of progress in
+these latter two in recent times.) There will also be a version of the
+\package{siunitx} package written in \package{expl3}, in parallel to the
+current \LaTeXe\ version. These developments will provide improvements to
+everyday \LaTeX\ users who haven't even heard of The \LaTeX{} Project.
+
+Looking towards the long term, \LaTeX3 as a document preparation system needs
+to be written almost from scratch. A high-level user syntax needs to be
+designed and scores of packages will be used as inspiration for the
+`out-of-the-box' default document templates. \LaTeXe\ has stood up to the test
+of time~--- some fifteen years and still going strong~--- and it is now time
+to write a successor that will survive another score.
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news01.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,153 @@
+% Copyright 2009 The LaTeX Project
+\documentclass{ltnews}
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+}
+
+\usepackage{url}
+\newcommand\TUG[1]{\textsc{tug}~#1}
+
+\publicationmonth{June}
+\publicationyear{2009}
+\publicationissue{2}
+
+\begin{document}
+\maketitle
+
+\section{\TeX~Live and the \textsf{expl3} code}
+
+\TeX~Live 2009 is almost upon us, and the \LaTeX3 team have been
+readying a new release of the experimental \LaTeX3 code for this.
+Very dramatic changes have occurred since the
+last public release of the code in \TeX~Live~2008; no backwards compatibility has been
+maintained (as warned in the beginning of the documentation) but we
+believe the changes made are all much for the better. Almost every
+single part of \textsf{expl3} has been scrutinized, resulting in a far
+more coherent code base.
+
+The \textsf{expl3} code is now considered to be much more stable than
+it was before; a comprehensive test suite has been written that helps
+to ensure that we don't make any mistakes as we change things in the
+future. In the process of writing the test
+suite, many minor bugs were fixed; we recommend such test suites for
+all similar developmental projects!
+Some small underlying changes are still expected in the
+\textsf{expl3} code, but major, disruptive, changes aren't planned.
+
+\section{Planned updates}
+
+Until now, the last update to \textsc{ctan} of the \textsf{expl3}
+bundle was for \TeX~Live~2008. Now that work on the code is happening
+on a semi-steady basis, we plan to keep updates rolling out to
+\textsc{ctan} more frequently. This will allow anyone who wishes to
+experiment with the new code to use the \TeX~Live or MiK\TeX\
+updaters to install a recent version without having to `check out' the
+\textsc{svn} repository and install the packages manually.
+
+\section{New members}
+
+We didn't say anything about it in the last status update, but Joseph
+Wright and Will Robertson are now members of the \LaTeX\ Team. They
+have been working fairly exclusively on the \textsf{expl3} code.
+
+It's worth repeating that \LaTeXe\ is essentially frozen in order to
+prevent any backwards compatibility problems. As desirable as it is
+to benefit from the new features offered by new engines \XeTeX\ and
+Lua\TeX, we cannot risk the stability of production servers running
+older versions of \LaTeXe\ which will inevitably end up processing
+documents written into the future.
+
+\LaTeX3 will not be inheriting the same restraints, so stay tuned.
+
+\newpage
+
+\section{Some specifics}
+
+Morten H\o gholm will be presenting the recent changes in much more detail at
+\TUG{2009}. Here are some quick specifics for those interested. New code written
+and broad changes made to the \textsf{expl3} modules:
+\begin{description}
+\item [More logical function names]
+  Many function names that were hold-outs from the \TeX\ naming system
+  have been changed to fit into the more logical scheme of \textsf{expl3}; e.g.,
+  \verb|\def:Npn| and \verb|\let:NN| are now \verb|\cs_set:Npn| and
+  \verb|\cs_set_eq:NN|.
+
+\item [Defining functions and conditionals]
+  Much thought was put into new ways to define
+  functions and conditionals with a minimum of code.
+  See \verb|\cs_set:Nn| and \verb|\prg_set_conditional:Nnn|.
+
+\item [Smart comparisons]
+  Comparisons can be made much more easily now, with familiar notation such as
+  \verb|\intexpr_compare_p:n{ #1+3 != \l_tmpa_int }|.
+
+\item [Data from variables] A new function argument specifier \texttt{V} has
+  been added for extracting information from variables of different types,
+  without needing to know the underlying variable structure. Some other
+  tidy-ups on the argument specifiers offered, partially as a result of the
+  addition of this new one.
+
+\item [l3msg] New module to deal with communication between \LaTeX3 code
+  and the user (info messages, warnings, and errors), including message
+  filtering partially inspired by the \textsf{silence} package.
+  \end{description}
+
+\section{The next six months}
+
+Having overhauled the \textsf{expl3} code, we now plan to perform an
+analogous process with the foundations of the
+\textsf{xpackages}. These are the higher-level packages that will
+provide the basic needs such as control of the page layout and rich
+document-level interaction with the user. As the groundwork for this
+layer of the document processing matures, we will be able to start
+building more packages for a \LaTeX3 kernel; these packages will also
+be usable on top of \LaTeXe\ and serve as broadly customisable
+templates for future document design.
+
+As gaps in the functionality offered by \textsf{expl3} are found (in
+some cases, we know that they exist already), the programming layer
+will be extended to support our needs. In other cases, wrappers around
+\TeX\ functions that can be more usefully handled at a higher level
+will be written.
+
+In terms of what we're planning to work on next, three \textsf{xpackage}s
+will take the focus of our attention.
+\begin{description}
+\item [xbase]
+  `\textsf{xbase}' is actually two packages: \textsf{xparse} and
+  \textsf{template}. These contain code for, respectively, defining new
+  document commands (such that a user would use; e.g., \verb|\section|,
+  \verb|\makebox|, \dots) and for handling keyval lists for user input and
+  document specification. \textsf{xparse} was presented at \TUG{1999}%
+  \footnote{\url{http://www.latex-project.org/papers/tug99.pdf}}
+  and Lars Hellstr\"om wrote some notes on \textsf{template} in 2000%
+  \footnote{\url{http://www.latex-project.org/papers/template-notes.pdf}}.
+  Functionality coverage for these packages is good but concepts need a good
+  ``airing''. There are various approaches taken for keyval input, some more
+  recent than the \textsf{template} code, so there are some alternatives to
+  evaluate.
+\item [galley2] Sophisticated handling for \mbox{constructing} paragraphs and
+  other document elements. Morten spoke on this at \TUG{2008}%
+  \footnote{\url{http://river-valley.tv/the-galley-module/}}.
+  Design needs to be revisited after some stress testing.
+\item [xor] This is the \LaTeX3 output routine for splitting the galley into
+  page and sub-page sized chunks. Ideas and code need work to move to
+  ``production ready'' status. Early developments with this package were
+  published by Frank in 2000%
+  \footnote{\url{http://www.latex-project.org/papers/xo-pfloat.pdf}}.
+\end{description}
+
+Expect to hear again from us at Christmas. If you'd like to discuss any
+of these ideas, please join us on the \textsc{latex-l} mailing list%
+\footnote{\url{http://www.latex-project.org/code.html}}.
+
+\end{document}
+
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news02.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,128 @@
+% Copyright 2009,2010 The LaTeX Project
+\documentclass{ltnews}
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+}
+
+\usepackage{url}
+
+\publicationmonth{January}
+\publicationyear{2010}
+\publicationissue{3}
+
+\begin{document}
+\maketitle
+\raisefirstsection
+
+\section{Happy New Year}
+
+Welcome to the holiday season edition of `news of our activities' for
+the \LaTeX3 team.
+
+\section{Recent developments}
+
+The last six months has seen two significant releases in the \LaTeX3 code.
+In the \textsc{ctan} repository for the \pkg{xpackages},\footnote{\url{http://mirror.ctan.org/tex-archive/macros/latex/contrib/xpackages/}} you'll find two items of interest:
+\begin{itemize}
+\item A revised version of \textsf{xparse}; and
+\item The new package \textsf{xtemplate}, a re-implementation of \textsf{template} with a new syntax.
+\end{itemize}
+Special thanks to Joseph Wright who handled the implementations above almost single-handedly (with lots of input and feedback from other members of the team and members of the \textsc{latex-l} mailing list).
+
+These two packages are designed for the \LaTeX\ package author who wishes to define document commands and designer interfaces in a high-level manner.
+
+\paragraph{\textsf{xparse}}
+This package allows complex document commands to be constructed with all sorts of optional arguments and flags. Think of how \verb|\newcommand| allows you to create a command with a single optional argument and \textsf{xparse} is a generalisation of that idea.
+
+\paragraph{\textsf{xtemplate}}
+This package requires more explanation.
+\textsf{Xtemplate} is designed to separate the logical information in a
+document from its visual representation. `Templates' are constructed to fulfil
+individual typesetting requirements for each set of arguments; to change
+the look of a certain part of a document, instantiations of templates can be
+swapped out for another without (a) having to change the markup of the source
+document, or (b) having to edit some internal \LaTeX\ macro.
+
+
+\LaTeXe{} packages, such as \textsf{geometry} or \textsf{titlesec}, already provide
+parameterized interfaces to specific document elements.  For example,
+one may use \textsf{titlesec} to change the
+layout of a \verb|\section|: one modifies its layout parameters via \verb|\titleformat| and \verb|\titlespacing|.
+In a way, such packages define a template for a specific document element and
+some manipulation commands to instantiate it.
+\pagebreak
+However, the moment the intended
+layout is not achievable with one package you are on your own: either you have
+to resort to low-level programming or find some other high-level package which, of course, comes with its own set of conventions and manipulation commands.
+
+The \textsf{xtemplate} package can be thought of a generalization of such
+ideas. It provides a uniform interface for defining and managing templates for
+any kind of document element and most importantly provides a uniform interface
+for instantiating the layout.
+
+Thus the designer activity of defining or modifying a document class is
+limited to selecting the document elements that should be provided by the
+class (e.g., \verb|\chapter|, \verb|\section| \verb|\footnote|, lists, \ldots), selecting
+appropriate ``named'' templates for each of them, and instantiating these
+templates by specifying values for their layout parameters. If a desired
+layout can't be achieved with a given template a different template for the
+same document element can be selected.
+
+Programming is only necessary
+if no suitable template for the intended layout is available.
+It is then that a \LaTeX{} programmer has to build a new template
+that supports the layout requirements. Once this task is complete, the
+template may be
+added to the selection of templates that designers and users may choose from
+to define or adjust document layouts seamlessly.
+
+This is a slight gloss over the complexities of the package itself, which you can read about in the documentation. We've tried to document \textsf{xtemplate} clearly but we'd love feedback on whether the ideas make sense to you.
+
+As an addendum to the introduction of \textsf{xtemplate}, the older \textsf{template} package will be retired in the near future. To our knowledge there is only a single package on \textsc{ctan} that uses \textsf{template}, namely \textsf{xfrac}, and members of the \LaTeX\ team are in the process of switching this package over to \textsf{xtemplate}. If you have any private code that uses \textsf{template}, please let us know!
+
+
+\section{Upcoming plans}
+
+Having announced the updated \textsf{xparse} and the new \textsf{xtemplate}, the next stage of development will revolve around using these two systems in the other components of the \textsf{xpackages}, feeding back our experience in practise with the original ideas behind the designs and evaluating if the packages are meeting our expectations.
+
+\subsection{Packages to tackle}
+
+\paragraph{\textsf{xhead}}
+The first work will be to create a new \textsf{xpackage} (probably called \textsf{xhead}), for typesetting section headings and other document divisions.
+Section headings are one of the more complex areas to work with, so
+the work should stress \textsf{xtemplate} enough to know if its
+current design is sufficient for most needs.  Nothing has been
+released yet, but we'll announce further developments on the
+\textsc{latex-l} mailing
+list\footnote{For details, see
+  \url{http://www.latex-project.org/code.html}} in the
+mean time.
+
+
+\paragraph{\textsf{galley}}
+We also need to give \textsf{galley} the same treatment as
+\textsf{xparse} and \textsf{xtemplate} have already had. That is, we have an
+older implementation (in fact two) that needs some work before we're ready to release it to \textsc{ctan}.
+
+The \textsf{galley} package is used to place material into the
+vertical list while typesetting but before page breaks occur. Since it
+works at such a low level, it is important to solidify this package
+before writing higher level design templates.
+
+An issue we have to face is that to achieve best results,
+\textsf{galley} cannot be used in concert with \LaTeXe\ code.  This
+could limit its usefulness, and we may decide that it's better to
+scale back the features we're attempting, to allow better
+interoperability for existing packages and documents.  More work
+remains before we can decide between these options.
+
+
+\end{document}
+
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news03.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,123 @@
+% Copyright 2009,2010 The LaTeX Project
+\documentclass{ltnews}
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+}
+
+\usepackage{url,hologo}
+
+\publicationmonth{July}
+\publicationyear{2010}
+\publicationissue{4}
+
+\begin{document}
+\maketitle
+
+\noindent
+Now that we're back from the \TeX\ Users Group conference in San
+Francisco, it's time to discuss what's been going on over the last six months.
+Due to some extra travel plans after the conference, this issue is slightly
+late in coming out.
+
+
+\section{\textsf{expl3} in practice}
+
+Joseph Wright and Will Robertson have both released significant new versions
+of their packages, resp., \textsf{siunitx} and \textsf{fontspec}. These have
+been re-written in the \LaTeX3 programming language \textsf{expl3}, which we
+have discussed here previously. Using \textsf{expl3} for production code has
+been very successful, both in demonstrating that the concepts are sound and
+highlighting areas that still need some attention.
+% The \textsf{expl3}
+% code will continue to evolve as more people use it for their work.
+
+In the case of \textsf{fontspec}, \textsf{expl3} programming is being used to
+target \LaTeX\ running on either \XeTeX\ and \hologo{LuaTeX}. In the latter
+case, the package is a mixture of Lua code and \pkg{expl3} code; Will
+presented the \pkg{unicode-math} package at TUG~2010, which is developed in
+the same style.
+
+
+\section{New \textsf{xpackages}}
+
+Frank Mittelbach has started to work on a new experimental \LaTeX3 package
+\textsf{xhead} that provides templates for one of the most complex areas of
+document design: section headings and document divisions. This
+is the beginning of an ambitious idea to map out the requirements for
+typesetting most documents currently processed with \LaTeX.
+
+One of the challenges here is providing a ``natural'' design language for
+describing the two-dimensional spatial relationships of objects participating
+in the design, e.g., the placement of a heading number in relation to the
+heading title, a possible sub-title, etc. In answer to this challenge Frank
+developed the \textsf{xcoffin} package, which he presented at TUG~2010. It is
+designed as a high-level interface for placing and aligning boxes on a page,
+allowing a `designer's approach' for indicating the positional relationship
+between boxes. (A `coffin' is a box with handles.) As an example, it is
+possible to represent ideas such as `align the lower-left corner of box A with
+the upper-right corner of box B after rotating it ninety degrees', without
+having to calculate the intermediate positions.
+
+We expect a future version of \textsf{xcoffin} (after some further work on its
+interface layer and its internal implementation) to play a major role in all
+packages providing layout templates for higher-level document objects, such as
+table of contents designs, floats, etc.
+
+Finally,
+Joseph Wright has begun work with the current `galley' packages, producing the
+new, minimal, \textsf{xgalley} based on \textsf{xfm-galley} as a testbed for
+what we need and what will work.
+
+
+\section{Developments with \textsf{expl3}}
+
+Meanwhile, Joseph's \emph{also} been writing a new floating-point calculation
+module, called \textsf{l3fp}, for \pkg{expl3}. This module allows manipulation
+and calculation of numbers with a much larger range than \TeX\ allows
+naturally. The \textsf{l3fp} module has already been utilised in the
+\pkg{xcoffin} code for calculatations such as coordinate rotations and
+intersection points of vectors.
+
+The modules \pkg{l3io} and \pkg{l3file} have been revised, rethinking the way
+that read and write streams are dealt with. \TeX\ has a hard limit of sixteen
+input and output streams open at any one time, and the new implementation for
+\pkg{expl3} provides more flexibility in how they are allocated; there's now
+much less chance of running into a `\verb|No room for a new \read|' (or
+\verb|\write|) error.
+
+Sometimes we discuss ideas for \textsf{expl3} that \emph{don't} end up making
+it into the final code. One example of this is the concept of having `local
+registers' for integers, boxes, and so on, that do not survive outside of the
+group they are defined in (in contrast to Plain \TeX\ and \LaTeX, where
+allocators such as \verb|\newcount| and \verb|\newbox| are always global).
+Despite the scope for some small benefit, we decided that the extra complexity
+that the additional functions required, in both syntax and documentation, was
+not justified.
+
+
+\section{TUG 2010 reflections}
+
+% added most of it back in: -fmi
+
+%% Most of the active \LaTeX3 Project team were able to attend the TUG~2010
+%% conference and (for Will) meet everyone in person for the first time.
+
+Our interpretation of the broad themes discussed at the conference are that
+\TeX-based systems are still thriving and there are some big problems to solve
+with robust solutions to transform \LaTeX\ source, including mathematics, into
+a form such as HTML. While there are big pushes for standardising various aspects
+of the \LaTeX\ syntax, we also believe that it is \LaTeX's very
+flexibility---its inherently non-standardised markup---that has allowed it to
+survive for so many years. There is a delicate trade-off here between moving
+forward into more standards-based territory while also retaining the
+extensibility of the third-party package system.
+
+\end{document}
+
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news04.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,64 @@
+% Copyright 2011 The LaTeX Project
+\documentclass{ltnews}
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+}
+
+\usepackage{hologo}
+
+\publicationmonth{January}
+\publicationyear{2011}
+\publicationissue{5}
+
+\begin{document}
+\maketitle
+
+
+\section{Happy new year}
+
+Seasons greetings for 2011!
+As the previous news issue was released late, this season's issue will be shorter than usual.
+
+\section{The LPPL is now OSI-approved}
+
+We are happy to report that earlier this year the \LaTeX\ Project Public License (LPPL) has been approved by the OSI as an open source licence.\footnote{\url{http://www.opensource.org/licenses/lppl}} Frank Mittelbach will be publishing further details on this news in a retrospective on the LPPL in an upcoming TUGboat article.
+
+\section{Reflections on 2010}
+
+We are pleased to see the continued development and discussion in the \TeX\ world.
+The \LaTeX\ ecosystem continues to see new developments and a selection of notable news from the second half of last year include:
+\begin{itemize}
+\item[June] The TUG~2010 conference was held very successfully in San
+Francisco; videos, slides, and papers from \LaTeX3 Project members are available from our website.\footnote{\url{http://www.latex-project.org/papers/}}
+\item[Aug.]
+The \TeX\ Stack Exchange\footnote{\url{http://tex.stackexchange.com}} question\,\&\,answer website was created and has since grown quickly. At time of writing, some 2800 people have asked 2600 questions with 5600 answers total, and 2200 users are currently visiting daily.
+\item[Sept.] \TeX\ Live 2010 was released: each year the shipping date is earlier; the production process is becoming more streamlined and we congratulate all involved for their hard work. One of the most notable new components of \TeX\ Live 2010 includes the `restricted shell escape' feature to allow, among other things, automatic EPS figure conversion for pdf\LaTeX\ documents.
+\item[Oct.] TLContrib\footnote{\url{http://tlcontrib.metatex.org/}} was opened by Taco Hoekwater as a way to update a \TeX~Live installation with material that is not distributable through \verb|tlmgr| itself. Such material includes executables (e.g., new versions of Lua\TeX), non-free code, or test versions of packages.
+\item[Nov.] Philipp Lehman released the first stable version of \textsf{biblatex}. One of the most ambitious \LaTeX\ packages in recent memory, \textsf{biblatex} is a highly flexible package for managing citation cross-referencing and bibliography typesetting. In `beta' status for some years now, reaching this point is a great milestone.
+\item[Dec.] Lua\TeX\ 0.65. We are happy to see Lua\TeX\ development steadily continuing. \LaTeX\ users may use Lua\TeX\ with the \verb|lualatex| program. Like \verb|xelatex|, this allows \LaTeX\ documents to use multilingual OpenType fonts and Unicode text input.
+\end{itemize}
+
+\section{Current progress}
+
+The \textsf{expl3} programming modules continue to see revision and expansion; we have added a Lua\TeX\ module, but \textsf{expl3} continues to support all three of pdf\LaTeX, \XeLaTeX, and Lua\LaTeX\ equally.
+
+The \textsf{l3fp} module for performing floating-point arithmetic has been extended and improved. Floating point maths is important for some of the calculations required for complex box typesetting performed in the new `coffins' code.
+The \textsf{l3coffin} module has been added based on the original \textsf{xcoffins} package introduced at TUG~2010 as reported in the last news issue; this code is now available from CTAN for testing and feedback.
+
+We have consolidated the \textsf{l3int} and \textsf{l3intexpr} modules (which were separate for historical purposes); all integer/count-related functions are now contained within the `\textsf{int}' code and have prefix \verb|\int_|. Backwards compatibility is provided for, but eventually we will drop support for the older \verb|\intexpr_| function names.
+
+\section{Plans for 2011}
+
+In the following year, we plan to use the current \LaTeX3 infrastructure to continue work in building high-level code for designing \LaTeX\ documents using the \textsf{xtemplate} package. Our first priority is to look at section headings and document divisions, as we see this area as one of the most difficult, design-wise, of the areas to address. From there we will broaden our scope to more document elements.
+
+We will also do some low-level work on the `galley', which is the code that \LaTeX3 uses to build material for constructing pages, and we will continue to extend \textsf{expl3} into a more complete system from which we can, one day, create a pure \LaTeX3 format.
+
+\end{document}
+
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news05.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,141 @@
+% Copyright 2011 The LaTeX Project
+\documentclass{ltnews}
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+}
+
+\usepackage{hologo}
+
+\publicationmonth{June}
+\publicationyear{2011}
+\publicationissue{6}
+
+\begin{document}
+\maketitle
+
+\noindent
+A key aim of releasing `stable' \LaTeX3 material to CTAN is to allow users to
+benefit from new ideas \emph{now}, and also to raise the profile of usable
+\LaTeX3 ideas. This is clearly being successful, with \pkg{xparse} being of
+particular utility to end users. This increase in interest has been
+particularly notable on the new
+\href{http://tex.stackexchange.com/}{TeX.SX Q\&A site}.
+
+\section{The \LaTeX3 Team expands}
+
+Raising interest in \LaTeX3 developments has inevitably led to feedback on
+cases where the code base has required attention. It has also attracted new
+programmers to using \LaTeX3 ideas, some more than others! Bruno Le Floch has
+over the past few months made many useful contributions to \LaTeX3, and we are
+very pleased that he has recently joined The \LaTeX{} Project.
+
+Bruno has taken a particular interest in improving the performance and
+reliability of the \pkg{expl3} language. This has already resulted in new
+implementations for the \texttt{prop} and \texttt{seq} data types. At the same
+time, he has identified and fixed several edge-case issues in core \pkg{expl3}
+macros.
+
+\section{The `Big Bang'}
+
+In parallel to Bruno's improvements, Joseph Wright initiated a series of `Big
+Bang' improvements to \LaTeX3. The aim of the Big Bang was to address a number
+of long-standing issues with the \LaTeX3 code base. Development has taken place
+over many years, with the status of some of the resulting code being less
+than clear, even to members of The \LaTeX{} Project! At the same time, different
+conventions had been applied to different parts of the code, which made reading
+some of the code rather `interesting'. A key part of the Big Bang has been to
+address these issues, cleaning up the existing code and ensuring that the
+status of each part is clear.
+
+The arrangement of \LaTeX3 code is now the same in the development
+repository and on CTAN, and splits the code into three parts.
+\begin{description}
+  \item[\pkg{l3kernel}] The core of \LaTeX3, code which
+    is expected to be used in a \LaTeX3 kernel in more or less the
+    current form. Currently, this part is made up of the \LaTeX3
+    programming layer, \pkg{expl3}.
+  \item[\pkg{l3packages}] \LaTeXe{} packages making use of \LaTeX3
+    concepts and with stable interfaces. The \pkg{xparse} and
+    \pkg{xtemplate} packages are the core of this area. While many of
+    the \emph{ideas} explored here may eventually appear in a \LaTeX3
+    kernel, the interfaces here are tied to \LaTeXe{}.
+  \item[\pkg{l3experimental}] \LaTeXe{} packages which explore more
+    experimental \LaTeX3 ideas, and which may see interface changes as
+    development continues. Over time, we expect code to move from this area
+    to either \pkg{l3kernel} or \pkg{l3packages}, as appropriate.
+\end{description}
+
+In addition to these release areas, the development code also features a
+\pkg{l3trial} section for exploring code ideas. Code in \pkg{l3trial} may be
+used to improve or replace other parts of \LaTeX3, or may simply be dropped!
+
+As well as these improvements to the \emph{code} used in \LaTeX3, much of the
+documentation for \pkg{expl3} has been made more precise as part of the Big
+Bang. This means that \texttt{source3.pdf} is now rather longer than it was
+previously, but also should mean that many of the inaccuracies in earlier
+versions have been removed. Of course, we are very pleased to receive
+suggestions for further improvement.
+
+\section{\LaTeX3 on GitHub}
+
+The core development repository for \LaTeX3 is held in an SVN repository, which
+is \href{http://www.latex-project.org/code.html}{publicly viewable \emph{via}
+the Project website}. However, this interface misses out on some of the `bells
+and whistles' of newer code-hosting sites such as
+\href{http://gitbug.com/}{GitHub} and \href{http://bitbucket.org/}{BitBucket}.
+We have therefore established a mirror of the master repository on GitHub%
+\footnote{\url{http://github.com/latex3/svn-mirror}}. This is kept in
+synchronisation with the main SVN repository by Will Robertson (or at least
+by his laptop!).
+
+The GitHub mirror offers several useful features for people who wish to
+follow the \LaTeX3 code changes. GitHub offers facilities such as highlighted
+differences and notification of changes. It also makes it possible for
+non-Team members to submit patches for \LaTeX3 as `pull requests' on
+GitHub.
+
+As well as offering a convenient interface to the \LaTeX3 code, the GitHub
+site also includes an issue database\footnote{%
+\url{http://github.com/latex3/svn-mirror/issues}}. Given the very
+active nature of \LaTeX3 development, and the transitory nature of many
+of the issues, this provides a better approach to tracking issues than
+the main \LaTeX{} bug database\footnote{\url{http://www.latex-project.org/bugs.html}}.
+Developers and users are
+therefore asked to report any issues with \LaTeX3 code \emph{via} the GitHub
+database, rather than on the main Project homepage.
+Discussion on the \href{http://www.latex-project.org/code.html}{\mbox{LaTeX-L} mailing list}
+is also encouraged.
+
+\section{Next steps}
+
+The `Big Bang' involves making a number of changes to \pkg{expl3} function
+names, and is likely to break at least some third-party code. As a result,
+the updates will not appear on the \TeX{} Live 2011 DVD release, but will
+instead be added to \TeX{} Live once regular updates restart (probably
+August).
+
+Bruno is working on a significant overhaul of the \pkg{l3fp} floating-point
+unit for \LaTeX3. He has developed an approach which allows expandable
+parsing of floating-point expressions, which will eventually allow syntax
+such as
+\begin{verbatim}
+  \fp_parse:n { 3 * 4 ( ln(5) + 1 ) }
+\end{verbatim}
+This will result in some changes in the interface for floating-point numbers, but
+we feel that the long-term benefit is worth a small amount of recoding in other
+areas.
+
+Joseph has completed documentation of the \pkg{xgalley} module, and this is
+currently being discussed. Joseph is hoping to move on to implement other
+more visible ideas based on the \pkg{xtemplate} concept over the next few
+months.
+
+\end{document}
+
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news06.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,111 @@
+% Copyright 2012 The LaTeX3 Project
+\documentclass{ltnews}
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+}
+
+\publicationmonth{February}
+\publicationyear{2012}
+\publicationissue{7}
+
+\begin{document}
+\maketitle
+
+\section{After the `Big Bang'}
+
+The last \LaTeX3 News gave details of the `Big Bang', in which the team have
+revised the layout and coverage of the \LaTeX3 codebase. This process has
+made the status of different modules clearer, so that both the team themselves
+and everyone else know what is going on.
+
+The `Big Bang' changes were not shipped to \textsc{ctan} until after the \TeX{}
+Live 2011 freeze, as we did not want to end up with a \textsc{dvd} containing
+badly broken code. The update went to \textsc{ctan} soon after \TeX{} Live 2011
+shipped, and has now propagated around the world. The new package naming
+(\pkg{l3kernel}, \pkg{l3packages} and \pkg{l3experimental}) has caused some
+surprises for a small number of users, but there have not been any major
+issues with the changes at the code level.
+
+The `Big Bang' has attracted attention from programmers outside of the
+\LaTeX3 team, with useful feedback arriving on the
+\texttt{LaTeX-L} list and TeX.sx, in particular. One area that this has
+highlighted is the need to document carefully when changes to the `stable'
+parts of the \LaTeX3 codebase occur. All changes to \pkg{l3kernel} now
+come with an explicit date for the change in the documentation, which means
+that programmers can check exactly when the features they want were introduced.
+
+Another key part of supporting \LaTeX3 use beyond the team is making it easy
+to check on the version of \LaTeX3 installed. To support that, the file date
+of the main \pkg{expl3} package is now set each time there is a release of the
+\LaTeX3 material to \textsc{ctan}. This means that the \LaTeXe{}
+\cs{@ifpackagelater} test can be used reliably to detect if the installed
+version of \LaTeX3 is going to supply the functions that a programmer is
+using.
+
+\section{Deforming boxes}
+
+Additions to both the \LaTeX3 stable material and more experimental modules
+continue. Joseph Wright has been working on adding `native' drivers for
+\LaTeX3 to support box transformations. These allow box rotation, clipping
+and scaling with the drivers \texttt{dvips}, \texttt{xdvipdfmx} and direct
+\textsc{pdf} output.
+
+The development of clipping support for the \texttt{xdvipdfmx} driver has also allowed
+us to suggest improvements to the \LaTeXe{} graphics drivers, enabling clipping
+with the \XeTeX{} engine.
+
+\section{A \TeX{}-based regex engine}
+
+Bruno Le Floch has been %working across the codebase, %% omitted to avoid page break
+improving the efficiency
+and robustness of a number of \LaTeX3 functions. Most notably, he has
+created a purely \TeX{}-based regular expression (regex) system for \LaTeX3.
+This is currently experimental, but is already proving useful and will
+hopefully stabilise over the coming months.
+
+Bruno's regex system works with all of the supported engines (pdf\TeX{},
+\XeTeX{} and \LuaTeX{}). He has implemented the core ideas of standard
+regex systems, along with some \TeX{}-specifics to allow matching and
+replacing
+the content of token lists % correct?
+by category code.
+
+\section{\pkg{xparse} improves}
+
+The \pkg{xparse} module has been overhauled, making the internal code
+more efficient and adding additional argument types. This has also allowed
+us to deal with a number of internal bugs, meaning that argument grabbing
+is now more reliable.
+
+The argument grabbers themselves have been reworked so that in the event of an error,
+the user will normally get a meaningful message from \TeX{} rather than
+one pointing to \pkg{xparse} internal function names. This should help
+in tracking down erroneous input in real documents.
+
+\section{The galley}
+
+As detailed in the last issue, work on the galley module has been continuing.
+Discussion of Joseph's reimplementation of the galley concepts highlighted
+some important areas to work on, with the nature of the template concept
+being particularly significant.
+
+More work is still needed to finalise the galley concepts, but it is clear that
+some of this will require feedback from other areas. Joseph therefore hopes
+to finish work on the current round of galley improvements by the end of
+February, and to return to them once some other areas have been addressed.
+
+\section{Relationships between document items}
+
+The \textsc{tug}2011 meeting took place in October in India. Frank Mittelbach
+spoke there about ideas for describing the design relationship between document elements.
+% omit calling it "ldb" here because that name will likely change (last I heard?)
+These ideas allow a document designer to specify the design of a document element
+based on its context within a document, and progress in this area will likely
+lead to an extension in the \pkg{xtemplate} system.
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news07.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,170 @@
+% Copyright 2012 The LaTeX3 Project
+\documentclass{ltnews}
+
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+}
+
+\usepackage{expl3,siunitx,catchfile}
+\usepackage{hologo}
+\usepackage{verbatim}% avoid ltnews' "special" verbatim processing
+
+\publicationmonth{July}
+\publicationyear{2012}
+\publicationissue{8}
+
+\def\DTX{\texttt{.dtx}}
+\def\STY{\texttt{.sty}}
+
+\ExplSyntaxOn
+\NewDocumentCommand { \calcnum } { m }
+  { \num { \fp_to_scientific:n {#1} } }
+\ExplSyntaxOff
+
+\begin{document}
+\maketitle
+
+\raisefirstsection
+\section{Extended floating point support}
+
+Bruno Le Floch has been re-writing the floating point module to function in an `expandable' manner. This allows floating point calculations to be computed far more flexibly and efficiently than before.
+The expandable nature of the new code allows its use inside operations such as writing to external files, for which previously any such calculations would have to be pre-calculated before any of the writing operations began.
+
+Bruno's work on the floating point module has been officially released into the main \textsc{svn} repository for \texttt{l3kernel}; \TeX\ Live 2012 will contain the `old' code for stability while this year is spent testing the new code in production environments and ironing out any wrinkles.
+
+Here's a neat example as suggested in the documentation, which produces `\calcnum { round ( 200 pi * sin ( 2.3 ^ 5 ) , 2 ) }':
+
+\begin{verbatim}
+\usepackage{xparse, siunitx}
+\ExplSyntaxOn
+\NewDocumentCommand { \calcnum } { m }
+  { \num { \fp_to_scientific:n {#1} } }
+\ExplSyntaxOff
+
+\calcnum {
+  round ( 200 pi * sin ( 2.3 ^ 5 ) , 2 )
+}
+\end{verbatim}
+
+This feature is invaluable for simple (and not-so-simple) calculations in document and package authoring, and has been lacking a robust solution for many years.
+While \hologo{LuaLaTeX} can perform similar tasks within its Lua environment, the floating point support is written using the \texttt{expl3} programming language only, and is thus available in \hologo{pdfLaTeX} and \hologo{XeLaTeX} as well.
+
+\section{Regular expressions in \TeX}
+
+As if expandable floating point support wasn't enough, Bruno has also written a complete regular expression engine in \texttt{expl3} as well.
+% [Ed: Consider my mind blown.]
+Many reading this will be familiar with the quote attributed to Jamie Zawinski:
+\begin{quote}\itshape
+Some people, when confronted with a problem, think
+``I know, I'll use regular expressions.''
+Now they have two problems.
+\end{quote}
+And as humorous as the saying is, it's still fair to say that regular expressions are a great tool for manipulating streams of text.
+We desperately hope that people will \emph{not} start using the regex code to do things like parse \textsc{xml} documents; however, for general search--replace duties, there's never been anything like \texttt{l3regex} for the \LaTeX\ world.
+As a trivial example, there are
+\CatchFileDef\thisfile{\jobname.tex}{}%
+\ExplSyntaxOn
+\exp_args:Nno \regex_count:nnN { \b (?i) W e \b  } {\thisfile} \l_tmpa_int
+\int_use:N \l_tmpa_int
+\ExplSyntaxOff
+~instances of the word `We' or `we' in this document (including those two).
+This value is counted automatically in two lines of code.
+
+And again, it is available for \hologo{pdfLaTeX} and \hologo{XeLaTeX} users as well as \hologo{LuaLaTeX} ones; it also bears noting that this provides an easy solution for applying regular expression processing to \LaTeX\ documents and text data even on the Windows operating system that does not have native support for such things.
+
+
+\section{Separating internal and external code}
+
+\LaTeX\ packages are written by a wide range of package authors and consist of code and commands for various purposes.
+Some of these commands will be intended for use by document authors (such as \verb|\pbox| from the \textsf{pbox} package); others are intended for use by other package writers (such as \verb|\@ifmtarg| from the \textsf{ifmtarg} package).
+
+However, a large portion of them are internal, i.e., are intended to
+be used only within the package or within the \LaTeX{} kernel and
+should not be used elsewhere. For example, \verb|\@float| is the
+\LaTeX{} kernel interface for floats to be used in class files, but
+the actual work is done by a command called \verb|\@xfloat| which
+should not be used directly. Unfortunately the \LaTeXe{} language
+makes no clear distinction between the two, so it is tempting for
+programmers to directly call the latter to save some ``unnecessary''
+parsing activity.
+
+The downside of this is that the ``internal'' commands suddenly act as
+interfaces and a reimplementation or fix in any of them would then
+break add-on packages as they rely on internal behavior. Over the
+course of the last twenty years probably 80\% of such ``internal''
+commands have found their way into one or another package.  The
+consequences of this is that nowadays it is next to impossible to
+change anything in the \LaTeXe{} kernel (even if it is clearly just an
+internal command) without breaking something.
+
+
+In \LaTeX3 we hope to improve this situation drastically by
+clearly separating public interfaces (that extension packages can use
+and rely on) and private functions and variables (that should not
+appear outside of their module).  There is (nearly) no way to enforce
+this without severe computing overhead, so we implement it only
+through a naming convention, and some support mechanisms.  However, we
+think that this naming convention is easy to understand and to follow,
+so that we are confident that this will be adopted and provides the
+desired results.
+
+\subsection{Naming convention for internals}
+
+We've been throwing around some ideas for this for a number of years but nothing quite fit; the issue comes down to the fact that \TeX\ does not have a `name-spacing' mechanism so any internal command needs to have a specific prefix to avoid clashing with other packages' commands.
+The prefix we have finally decided on for \textsf{expl3} code is a double underscore, such that functions like \verb|\seq_count:N| are intended for external use and \verb|\__seq_item:n| is an internal command that should not be used or relied upon by others.
+
+All this is well and good, but it can be inconvenient to type long prefixes such as \verb|\__seq_| before all command names, especially in a package for which nearly \emph{all} package functions are internal.
+
+We therefore also extended \textsf{DocStrip} slightly by adding  a `shorthand' for internal package prefixes.
+Commands and variables in \DTX\ code may now contain \texttt{@@} which is expanded to the function prefix when the \STY\ file is extracted.
+As an example, writing
+\begin{verbatim}
+  %<@@=seq>
+  \cs_new:Npn \@@_item:n
+    ...
+\end{verbatim}
+is equivalent to
+\begin{verbatim}
+  \cs_new:Npn \__seq_item:n
+    ...
+\end{verbatim}
+There are clear advantages to this syntax.
+Function names are shorter and therefore easier to type, and code can still be prototyped using the \texttt{@@} syntax
+(e.g., pasting code between a \DTX\ file and a regular \texttt{.tex} document).
+Most importantly, it is explicitly clear from the code source which commands are intended to be used externally and which should be avoided.
+
+We hope that this syntax will prove popular; in our initial experiments we think it works very well. In fact we found a good number of smaller errors when being forced to think about what is internal and what is an external function.
+
+\section{Continual revolution---the `small bang'}
+
+In addition to the major additions introduced above, Frank Mittelbach has been examining \texttt{expl3} with a fresh eye to resolve any outstanding issues in the consistency or logic of the names of functions.
+
+We are very mindful of the fact that for people to find \texttt{expl3} a useful tool, it must have a stable interface.
+This said, there are still some musty corners that we can show where people simply haven't been using certain functions.
+In select cases, we're re-assessing whether all of the (sometimes esoteric) odds and ends that have been added to \texttt{expl3} really belong; in other cases, it's now clear that some naming or behaviour choices weren't correct the first time around.
+
+To address this tarnish, we're carefully making some minor changes to parts of the \texttt{expl3} interface and we'd like to allay any fears that \texttt{expl3} isn't stable.
+The \texttt{expl3} language now offers a wide range of functions plus their variants, and we're talking about changing but a very small percentage of these, and not common ones at that.
+We don't want it to become a mess, so we think it's better to tidy things up as we go.
+Follow the \texttt{LaTeX-L} mailing list for such details as they arise.
+
+\end{document}
+
+
+dropped/replaced:
+
+The \LaTeX3 codebases ranges between these two extremes; the packages
+in \texttt{l3packages} are largely the former while the modules
+composing \textsf{expl3} are largely the latter type.  In both cases,
+the `external' commands (whether for document author or package
+writer) are usually defined in terms of other internal package
+commands that should not be used by anyone else, but often when
+reading the internal package code it's not always clear which is
+which.
+
+For \LaTeX3 we are experimenting with an extension to the \textsf{DocStrip} mechanism to provide a clear distinction between internal and external package commands.


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news08.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,1433 @@
+% Copyright 2014 The LaTeX3 Project
+\documentclass{ltnews}
+
+\PassOptionsToPackage{colorlinks}{hyperref}
+\usepackage{metalogo,ragged2e}
+
+\AtBeginDocument{
+  \renewcommand{\LaTeXNews}{\LaTeX3~News}
+  \RaggedRight
+  \setlength\parindent{1em}
+}
+
+\hbadness=10000
+\def\Dash{\,---\,}
+
+\providecommand\LuaLaTeX{Lua\LaTeX}
+\setcounter{tocdepth}{2}
+
+\usepackage{enumitem,csquotes}
+\MakeOuterQuote{"}
+\usepackage{fancyvrb}% to allow \Verb"<ul>" to typeset properly since ltnews patches \verb
+
+\makeatletter
+\renewcommand{\@subheadingfont}{%
+   \sffamily\slshape
+   \let\LaTeX\cmssLaTeX\let\TeX\cmssTeX
+}
+\renewcommand{\subsection}{%
+   \@startsection
+      {subsection}{2}{\z@}{-1.3ex \@plus -1ex \@minus -.2ex}%
+      {0.8ex \@plus.2ex}{\@subheadingfont}%
+}
+\makeatother
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\RequirePackage{tikz}
+\definecolor{basecolor}{RGB}{0,128,128}
+\definecolor{maincolor}{RGB}{55,200,113}
+
+
+\newcommand \explbanner{%
+\begin{tikzpicture}[y=0.80pt,x=0.80pt,yscale=-1, inner sep=0pt, outer sep=0pt]
+  \path[fill=basecolor,rounded corners=0.0000cm] (248.7785,295.7529) rectangle
+    (465.3586,478.5802);
+  \path[fill=white,rounded corners=0.0000cm] (257.9199,304.5427) rectangle
+    (456.2172,469.7905);
+  \path[fill=basecolor] (283.2386,478.5760) -- (289.5259,453.4125) .. controls
+    (302.2770,439.6121) and (314.0060,425.3008) .. (319.5695,407.9067) .. controls
+    (355.0759,401.0374) and (383.7853,403.5174) .. (413.7371,404.2858) .. controls
+    (411.0072,403.8309) and (322.2852,388.7992) .. (322.2852,388.7992) .. controls
+    (298.7181,356.5528) and (264.6380,373.5409) .. (249.0663,403.2205) --
+    (248.7470,478.6397) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=1.253pt]
+    (288.4249,394.4251) -- (288.2061,394.8313) .. controls (287.2860,396.5455) and
+    (285.7381,397.6863) .. (283.5499,398.3938) .. controls (281.3616,399.1013) and
+    (278.5647,399.3476) .. (275.2999,399.2063) -- (273.2374,399.1126) --
+    (274.7061,400.5501) .. controls (275.4640,401.2791) and (275.6960,401.8541) ..
+    (275.7061,402.3626) .. controls (275.7162,402.8712) and (275.5103,403.4284) ..
+    (275.0186,404.0501) .. controls (274.0353,405.2935) and (272.0593,406.6472) ..
+    (270.2374,408.0189) -- (269.6749,408.4564) -- (270.0499,409.0501) .. controls
+    (271.5698,411.3818) and (272.2617,413.2035) .. (272.4249,414.5814) .. controls
+    (272.5880,415.9592) and (272.2796,416.9162) .. (271.6436,417.7689) .. controls
+    (270.3717,419.4743) and (267.6257,420.6198) .. (265.1124,422.0501) --
+    (264.6124,422.3314) -- (264.7061,422.8626) .. controls (264.9221,424.1742) and
+    (264.5793,425.2316) .. (263.6436,426.3001) .. controls (262.7079,427.3687) and
+    (261.1571,428.4020) .. (259.0498,429.3001) -- (258.4873,429.5189) --
+    (258.5810,430.1126) .. controls (259.0013,432.9207) and (259.8134,435.3978) ..
+    (261.5810,436.9564) .. controls (263.1945,438.3790) and (265.6272,438.7418) ..
+    (268.7373,438.1126) .. controls (269.2811,441.1124) and (270.0885,443.8463) ..
+    (271.8935,445.6439) .. controls (273.7365,447.4793) and (276.5967,448.0631) ..
+    (280.5185,447.0189) .. controls (281.3879,449.0885) and (282.6104,450.5771) ..
+    (284.0498,451.5501) .. controls (285.6426,452.6269) and (287.4312,453.1746) ..
+    (289.1435,453.7064) -- (289.5810,452.2376) .. controls (287.8816,451.7099) and
+    (286.2778,451.1522) .. (284.9248,450.2376) .. controls (283.5718,449.3230) and
+    (282.4412,448.0628) .. (281.6748,445.8939) -- (281.4248,445.1751) --
+    (280.7060,445.3939) .. controls (276.7309,446.6155) and (274.5047,446.0613) ..
+    (272.9873,444.5501) .. controls (271.4699,443.0389) and (270.6337,440.3179) ..
+    (270.1123,437.1439) -- (269.9873,436.3001) -- (269.1435,436.5189) .. controls
+    (265.8672,437.3737) and (263.9323,436.9328) .. (262.6123,435.7689) .. controls
+    (261.3919,434.6928) and (260.6559,432.7860) .. (260.2373,430.4251) .. controls
+    (262.1657,429.5404) and (263.7732,428.5395) .. (264.8310,427.3314) .. controls
+    (265.8589,426.1576) and (266.3097,424.7444) .. (266.2373,423.2376) .. controls
+    (268.5457,421.9725) and (271.2938,420.8514) .. (272.8935,418.7064) .. controls
+    (273.7344,417.5788) and (274.1920,416.1226) .. (273.9873,414.3939) .. controls
+    (273.8023,412.8317) and (273.0178,411.0042) .. (271.7060,408.8626) .. controls
+    (273.3411,407.6578) and (275.1128,406.4408) .. (276.2373,405.0189) .. controls
+    (276.8610,404.2302) and (277.3196,403.3287) .. (277.2998,402.3314) .. controls
+    (277.2890,401.7896) and (277.0912,401.2653) .. (276.7998,400.7376) .. controls
+    (279.5102,400.7514) and (281.9952,400.5582) .. (284.0498,399.8939) .. controls
+    (286.3053,399.1646) and (288.0426,397.8495) .. (289.2060,396.0189) .. controls
+    (292.5635,396.0371) and (296.0636,396.7806) .. (299.5810,397.2376) .. controls
+    (303.1955,397.7073) and (306.8484,397.8601) .. (310.3310,396.3314) --
+    (309.7060,394.8939) .. controls (306.6247,396.2464) and (303.2846,396.1632) ..
+    (299.7685,395.7064) .. controls (296.2524,395.2495) and (292.5819,394.3984) ..
+    (288.8935,394.4251) -- (288.4248,394.4251) -- cycle;
+  \path[fill=white] (301.5159,393.8637) .. controls (301.5159,397.5244) and
+    (298.5484,400.4920) .. (294.8877,400.4920) .. controls (291.2270,400.4920) and
+    (288.2595,397.5244) .. (288.2595,393.8637) .. controls (288.2595,390.2031) and
+    (291.2270,387.2355) .. (294.8877,387.2355) .. controls (298.5484,387.2355) and
+    (301.5159,390.2031) .. (301.5159,393.8637) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=1.253pt]
+    (321.0186,387.9251) .. controls (315.0680,395.6662) and (313.8600,393.4088) ..
+    (310.2374,394.7063) -- (309.6124,394.9251) -- (309.7374,395.5813) .. controls
+    (311.1321,403.3566) and (315.5160,405.7238) .. (319.1124,408.5501) --
+    (320.0811,407.3313) .. controls (316.4798,404.5012) and (312.9249,402.6094) ..
+    (311.4874,396.0188) .. controls (314.1361,395.3813) and (316.6278,396.2007) ..
+    (322.2686,388.8626) -- (321.0186,387.9251) -- cycle;
+  \path[fill=maincolor] (301.5159,393.8637) .. controls (301.5159,397.5244) and
+    (298.5484,400.4920) .. (294.8877,400.4920) .. controls (291.2270,400.4920) and
+    (288.2595,397.5244) .. (288.2595,393.8637) .. controls (288.2595,390.2031) and
+    (291.2270,387.2355) .. (294.8877,387.2355) .. controls (298.5484,387.2355) and
+    (301.5159,390.2031) .. (301.5159,393.8637) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=1.253pt]
+    (294.8936,386.4563) .. controls (290.8098,386.4563) and (287.4874,389.7788) ..
+    (287.4874,393.8626) .. controls (287.4874,397.9464) and (290.8098,401.2688) ..
+    (294.8936,401.2688) .. controls (298.9774,401.2688) and (302.2999,397.9464) ..
+    (302.2999,393.8626) .. controls (302.2999,389.7788) and (298.9774,386.4563) ..
+    (294.8936,386.4563) -- cycle(294.8936,388.0188) .. controls
+    (298.1312,388.0188) and (300.7374,390.6250) .. (300.7374,393.8626) .. controls
+    (300.7374,397.1002) and (298.1312,399.7063) .. (294.8936,399.7063) .. controls
+    (291.6560,399.7063) and (289.0499,397.1002) .. (289.0499,393.8626) .. controls
+    (289.0499,390.6250) and (291.6560,388.0188) .. (294.8936,388.0188) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=1.253pt]
+    (291.5499,370.7063) .. controls (288.4841,370.7722) and (285.4193,371.2673) ..
+    (282.4249,372.1438) .. controls (269.6164,375.8932) and (256.6677,387.2311) ..
+    (248.7622,400.8596) -- (248.7662,404.0176) .. controls (256.4832,389.5161) and
+    (269.8419,377.4553) .. (282.8625,373.6438) .. controls (286.1465,372.6825) and
+    (289.4914,372.1880) .. (292.8312,372.2376) .. controls (302.8507,372.3862) and
+    (312.9146,377.4187) .. (321.6437,389.3626) -- (321.8312,389.6126) --
+    (322.1437,389.6751) .. controls (322.1437,389.6751) and (383.4924,400.0668) ..
+    (402.2375,403.2376) .. controls (376.3035,402.3430) and (350.4290,401.2333) ..
+    (319.3937,407.2376) -- (318.9250,407.3313) -- (318.8000,407.7688) .. controls
+    (313.2958,424.9775) and (301.6553,439.2096) .. (288.9250,452.9875) --
+    (288.8000,453.1125) -- (288.7375,453.3313) -- (282.4611,478.5810) --
+    (283.9307,478.5810) -- (290.2375,453.8937) .. controls (302.8375,440.2444) and
+    (314.4843,426.0036) .. (320.1437,408.7062) .. controls (355.3332,401.9651) and
+    (383.8501,404.4090) .. (413.7062,405.1750) -- (413.8312,403.6125) .. controls
+    (413.8282,403.6120) and (413.7403,403.6129) .. (413.7375,403.6125) .. controls
+    (410.8928,403.1379) and (323.2219,388.2676) .. (322.6750,388.1750) .. controls
+    (313.7728,376.1342) and (303.2902,370.9006) .. (292.8625,370.7062) .. controls
+    (292.4247,370.6982) and (291.9880,370.6972) .. (291.5500,370.7062) -- cycle;
+  \path[fill=maincolor,miter limit=4.00,line width=0.977pt] (370.0353,433.6332) --
+    (333.5033,433.6332) -- (333.5033,428.6205) .. controls (334.6678,428.5193) and
+    (335.9083,428.4180) .. (337.2248,428.3167) .. controls (338.5413,428.1648) and
+    (339.6299,427.9623) .. (340.4907,427.7091) .. controls (341.9084,427.2534) and
+    (342.9717,426.4686) .. (343.6806,425.3547) .. controls (344.3895,424.1901) and
+    (344.7439,422.6964) .. (344.7439,420.8736) -- (344.7439,334.1385) .. controls
+    (344.7439,332.3158) and (344.3388,330.6195) .. (343.5287,329.0498) .. controls
+    (342.7692,327.4296) and (341.7565,326.1638) .. (340.4907,325.2523) .. controls
+    (339.5793,324.6448) and (337.9084,324.0878) .. (335.4780,323.5814) .. controls
+    (333.0476,323.0752) and (331.0982,322.7714) .. (329.6298,322.6700) --
+    (329.6298,317.8092) -- (357.8073,316.0623) -- (358.8706,317.2016) --
+    (358.8706,419.9622) .. controls (358.8706,421.7344) and (359.1997,423.2028) ..
+    (359.8580,424.3673) .. controls (360.5162,425.4813) and (361.5795,426.3420) ..
+    (363.0479,426.9496) .. controls (364.1618,427.4560) and (365.2504,427.8357) ..
+    (366.3138,428.0889) .. controls (367.4277,428.3420) and (368.6682,428.5193) ..
+    (370.0353,428.6205) -- (370.0353,433.6332);
+  \path[color=black,fill=white,nonzero rule,line width=0.977pt]
+    (357.7812,315.4375) -- (329.5938,317.1875) -- (329.0312,317.2500) --
+    (329.0312,317.8125) -- (329.0312,322.6562) -- (329.0312,323.2500) --
+    (329.5938,323.2813) .. controls (331.0155,323.3795) and (332.9294,323.6847) ..
+    (335.3438,324.1875) .. controls (337.7273,324.6842) and (339.3512,325.2404) ..
+    (340.1250,325.7500) .. controls (340.1300,325.7530) and (340.1517,325.7471) ..
+    (340.1563,325.7500) .. controls (341.3216,326.5942) and (342.2496,327.7784) ..
+    (342.9688,329.3125) -- (343.0001,329.3438) .. controls (343.7660,330.8280) and
+    (344.1251,332.3928) .. (344.1251,334.1251) -- (344.1251,420.8751) .. controls
+    (344.1251,422.6188) and (343.7916,423.9876) .. (343.1563,425.0313) .. controls
+    (342.5262,426.0216) and (341.6206,426.7047) .. (340.3126,427.1251) .. controls
+    (339.5087,427.3615) and (338.4639,427.5701) .. (337.1876,427.7188) .. controls
+    (337.1753,427.7198) and (337.1687,427.7178) .. (337.1563,427.7188) .. controls
+    (335.8502,427.8194) and (334.5947,427.8995) .. (333.4375,428.0001) --
+    (332.9063,428.0626) -- (332.9063,428.6251) -- (332.9063,433.6251) --
+    (332.9063,434.2501) -- (333.5000,434.2501) -- (370.0313,434.2501) --
+    (370.0313,433.6251) -- (370.6563,433.6251) -- (370.6563,428.6251) --
+    (370.6563,428.0626) -- (370.0938,428.0001) .. controls (368.7631,427.9015) and
+    (367.5404,427.7420) .. (366.4688,427.5001) .. controls (366.4598,427.4981) and
+    (366.4466,427.5021) .. (366.4375,427.5001) .. controls (365.4251,427.2570) and
+    (364.3851,426.8939) .. (363.3125,426.4063) -- (363.2812,426.3750) .. controls
+    (361.9048,425.8055) and (360.9567,425.0472) .. (360.3750,424.0625) .. controls
+    (359.7820,423.0135) and (359.4687,421.6654) .. (359.4687,419.9688) --
+    (359.4687,317.1875) -- (359.4687,316.9688) -- (359.3125,316.7813) --
+    (358.2500,315.6563) -- (358.0625,315.4375) -- (357.7812,315.4375) --
+    cycle(357.5625,316.6875) -- (358.2500,317.4062) -- (358.2500,419.9688) ..
+    controls (358.2500,421.8165) and (358.5889,423.3762) .. (359.3125,424.6562) --
+    (359.3438,424.6875) .. controls (360.0742,425.9238) and (361.2340,426.8546) ..
+    (362.7813,427.5000) .. controls (362.7903,427.5041) and (362.8037,427.4960) ..
+    (362.8126,427.5000) .. controls (363.9485,428.0145) and (365.0908,428.4264) ..
+    (366.1876,428.6875) .. controls (367.1668,428.9101) and (368.2823,429.0175) ..
+    (369.4376,429.1250) -- (369.4376,433.0313) -- (334.1251,433.0313) --
+    (334.1251,429.1875) .. controls (335.1314,429.1017) and (336.1652,429.0234) ..
+    (337.2813,428.9375) .. controls (338.6211,428.7830) and (339.7464,428.5489) ..
+    (340.6563,428.2813) -- (340.6876,428.2813) .. controls (342.2151,427.7903) and
+    (343.4000,426.9252) .. (344.1876,425.6875) .. controls (344.9701,424.4021) and
+    (345.3439,422.7770) .. (345.3439,420.8750) -- (345.3439,334.1250) .. controls
+    (345.3439,332.2119) and (344.9169,330.4366) .. (344.0626,328.7813) --
+    (344.0939,328.7813) .. controls (343.2978,327.0829) and (342.2020,325.7280) ..
+    (340.8439,324.7500) .. controls (339.7893,324.0471) and (338.0571,323.4821) ..
+    (335.5939,322.9688) .. controls (333.3923,322.5102) and (331.6955,322.2871) ..
+    (330.2502,322.1563) -- (330.2502,318.3750) -- (357.5627,316.6875) -- cycle;
+  \path[fill=basecolor,miter limit=4.00,line width=0.977pt] (411.1244,461.3551) ..
+    controls (406.3648,461.3550) and (402.0103,460.7474) .. (398.0609,459.5323) ..
+    controls (394.1115,458.3677) and (390.7191,456.7727) .. (387.8836,454.7474) ..
+    controls (385.0481,452.7220) and (382.8456,450.3929) .. (381.2759,447.7600) ..
+    controls (379.7569,445.1270) and (378.9974,442.4181) .. (378.9974,439.6333) ..
+    controls (378.9974,437.1523) and (379.6050,434.9244) .. (380.8202,432.9497) ..
+    controls (382.0354,430.9244) and (383.9848,429.9117) .. (386.6684,429.9117) ..
+    controls (389.7064,429.9117) and (392.0102,430.6712) .. (393.5799,432.1902) ..
+    controls (395.2001,433.6586) and (396.0103,435.3548) .. (396.0103,437.2789) ..
+    controls (396.0103,438.8991) and (395.7318,440.9498) .. (395.1748,443.4308) ..
+    controls (394.6685,445.9118) and (394.2634,447.6840) .. (393.9596,448.7473) ..
+    controls (394.3140,449.2030) and (394.9470,449.8106) .. (395.8584,450.5701) ..
+    controls (396.8204,451.3296) and (397.9850,452.0132) .. (399.3521,452.6208) ..
+    controls (400.9723,453.3803) and (402.6686,453.9879) .. (404.4408,454.4436) ..
+    controls (406.2129,454.8993) and (408.7192,455.1271) .. (411.9598,455.1272) ..
+    controls (414.9978,455.1271) and (417.9092,454.6208) .. (420.6941,453.6081) ..
+    controls (423.5295,452.5955) and (426.0106,450.9752) .. (428.1372,448.7473) ..
+    controls (430.3650,446.4182) and (432.0866,443.6840) .. (433.3018,440.5447) ..
+    controls (434.5676,437.4561) and (435.2005,433.3801) .. (435.2006,428.3167) ..
+    controls (435.2005,425.5825) and (434.8967,422.8736) .. (434.2892,420.1901) ..
+    controls (433.7322,417.5065) and (432.6689,415.1774) .. (431.0993,413.2026) ..
+    controls (429.5296,411.2280) and (427.3777,409.7090) .. (424.6435,408.6456) ..
+    controls (421.9599,407.5317) and (418.5421,406.9747) .. (414.3902,406.9747) --
+    (404.4408,406.9747) -- (404.4408,398.2404) -- (411.0484,398.2404) .. controls
+    (418.0358,398.2405) and (423.0738,396.3164) .. (426.1625,392.4682) .. controls
+    (429.2511,388.6201) and (430.7954,382.8226) .. (430.7955,375.0756) .. controls
+    (430.7954,368.7465) and (429.3017,363.9870) .. (426.3144,360.7970) .. controls
+    (423.3270,357.5565) and (419.0991,355.9363) .. (413.6307,355.9362) .. controls
+    (410.9978,355.9363) and (408.8205,356.2654) .. (407.0990,356.9235) .. controls
+    (405.4281,357.5312) and (404.0610,358.1388) .. (402.9977,358.7463) .. controls
+    (401.7318,359.4553) and (400.6939,360.2401) .. (399.8838,361.1008) .. controls
+    (399.0736,361.9616) and (398.4660,362.5946) .. (398.0609,362.9995) .. controls
+    (398.4153,364.6199) and (398.8457,366.6199) .. (399.3521,368.9996) .. controls
+    (399.8584,371.3288) and (400.1116,373.5567) .. (400.1116,375.6832) .. controls
+    (400.1116,377.5567) and (399.3014,379.2529) .. (397.6812,380.7719) .. controls
+    (396.1115,382.2403) and (393.7824,382.9745) .. (390.6938,382.9744) .. controls
+    (388.0102,382.9745) and (386.0355,382.0125) .. (384.7697,380.0883) .. controls
+    (383.5544,378.1643) and (382.9468,375.9365) .. (382.9469,373.4047) .. controls
+    (382.9468,370.7718) and (383.6810,368.0883) .. (385.1494,365.3540) .. controls
+    (386.6178,362.6199) and (388.7950,360.0629) .. (391.6811,357.6830) .. controls
+    (394.5672,355.3033) and (398.0862,353.3793) .. (402.2382,351.9108) .. controls
+    (406.3901,350.4425) and (411.1750,349.7083) .. (416.5928,349.7083) .. controls
+    (422.8207,349.7083) and (427.9599,350.6451) .. (432.0107,352.5184) .. controls
+    (436.1119,354.3413) and (439.3271,356.5692) .. (441.6564,359.2020) .. controls
+    (443.9348,361.7844) and (445.5044,364.4933) .. (446.3653,367.3287) .. controls
+    (447.2260,370.1642) and (447.6564,372.5947) .. (447.6564,374.6199) .. controls
+    (447.6563,377.1517) and (447.3019,379.7087) .. (446.5931,382.2909) .. controls
+    (445.8842,384.8226) and (444.7196,387.1771) .. (443.0994,389.3543) .. controls
+    (441.3272,391.7341) and (438.9727,393.9113) .. (436.0360,395.8860) .. controls
+    (433.1499,397.8101) and (429.5043,399.3797) .. (425.0992,400.5949) --
+    (425.0992,401.8101) .. controls (427.9346,402.0633) and (430.9473,402.6962) ..
+    (434.1373,403.7089) .. controls (437.3778,404.7216) and (440.2892,406.2152) ..
+    (442.8716,408.1899) .. controls (445.5551,410.2659) and (447.7576,412.9495) ..
+    (449.4792,416.2406) .. controls (451.2007,419.4812) and (452.0615,423.6078) ..
+    (452.0615,428.6205) .. controls (452.0615,438.3422) and (448.1627,446.2156) ..
+    (440.3652,452.2410) .. controls (432.5676,458.3170) and (422.8207,461.3550) ..
+    (411.1244,461.3551);
+  \path[color=black,fill=white,nonzero rule,line width=0.977pt]
+    (416.5938,349.0938) .. controls (411.1208,349.0938) and (406.2619,349.8476) ..
+    (402.0312,351.3438) .. controls (397.8235,352.8319) and (394.2307,354.7869) ..
+    (391.2812,357.2188) .. controls (388.3458,359.6393) and (386.1373,362.2465) ..
+    (384.6250,365.0625) .. controls (383.1180,367.8687) and (382.3437,370.6599) ..
+    (382.3438,373.4062) .. controls (382.3437,376.0357) and (382.9702,378.3800) ..
+    (384.2500,380.4062) -- (384.2500,380.4375) .. controls (385.6247,382.5272) and
+    (387.8580,383.5938) .. (390.6875,383.5938) .. controls (393.8729,383.5938) and
+    (396.3782,382.8237) .. (398.0938,381.2188) .. controls (399.8054,379.6142) and
+    (400.7187,377.7371) .. (400.7188,375.6875) .. controls (400.7187,373.5126) and
+    (400.4520,371.2419) .. (399.9375,368.8750) .. controls (399.4598,366.6301) and
+    (399.0615,364.7892) .. (398.7188,363.2188) .. controls (399.1249,362.8074) and
+    (399.6263,362.2937) .. (400.3438,361.5313) .. controls (401.1024,360.7253) and
+    (402.0588,359.9659) .. (403.2812,359.2813) -- (403.3125,359.2813) .. controls
+    (404.3323,358.6986) and (405.6639,358.0996) .. (407.3125,357.5000) .. controls
+    (408.9371,356.8790) and (411.0429,356.5314) .. (413.6250,356.5313) .. controls
+    (418.9728,356.5314) and (423.0134,358.1148) .. (425.8750,361.2188) .. controls
+    (428.7247,364.2617) and (430.1875,368.8295) .. (430.1875,375.0625) .. controls
+    (430.1875,382.7284) and (428.6509,388.4017) .. (425.6875,392.0938) .. controls
+    (422.7395,395.7667) and (417.9378,397.6251) .. (411.0625,397.6250) --
+    (404.4375,397.6250) -- (403.8438,397.6250) -- (403.8438,398.2500) --
+    (403.8438,406.9688) -- (403.8438,407.5938) -- (404.4375,407.5938) --
+    (414.3750,407.5938) .. controls (418.4724,407.5938) and (421.8256,408.1476) ..
+    (424.4063,409.2188) -- (424.4376,409.2188) .. controls (427.0895,410.2502) and
+    (429.1296,411.7125) .. (430.6251,413.5938) .. controls (432.1327,415.4906) and
+    (433.1477,417.7115) .. (433.6876,420.3125) .. controls (434.2853,422.9526) and
+    (434.5938,425.6236) .. (434.5938,428.3125) .. controls (434.5938,433.3250) and
+    (433.9715,437.3322) .. (432.7501,440.3125) -- (432.7188,440.3125) .. controls
+    (431.5305,443.3821) and (429.8590,446.0423) .. (427.6875,448.3125) .. controls
+    (425.6226,450.4758) and (423.2475,452.0501) .. (420.5000,453.0313) .. controls
+    (417.7822,454.0196) and (414.9389,454.5313) .. (411.9688,454.5313) .. controls
+    (408.7568,454.5313) and (406.2790,454.2771) .. (404.5938,453.8438) .. controls
+    (402.8574,453.3973) and (401.2103,452.8056) .. (399.6250,452.0625) --
+    (399.5938,452.0625) .. controls (398.2643,451.4717) and (397.1638,450.8152) ..
+    (396.2500,450.0938) .. controls (395.4421,449.4205) and (394.9503,448.9158) ..
+    (394.6250,448.5313) .. controls (394.9285,447.4218) and (395.3093,445.8751) ..
+    (395.7812,443.5625) .. controls (396.3444,441.0538) and (396.6250,438.9715) ..
+    (396.6250,437.2813) .. controls (396.6250,435.1859) and (395.7186,433.3075) ..
+    (394.0000,431.7500) .. controls (392.2889,430.0942) and (389.7960,429.3125) ..
+    (386.6562,429.3125) .. controls (383.8191,429.3125) and (381.5985,430.4297) ..
+    (380.2812,432.6250) -- (380.3125,432.6250) .. controls (379.0375,434.6970) and
+    (378.3750,437.0443) .. (378.3750,439.6250) .. controls (378.3750,442.5209) and
+    (379.1845,445.3489) .. (380.7500,448.0625) .. controls (382.3672,450.7752) and
+    (384.6374,453.1829) .. (387.5313,455.2500) .. controls (390.4308,457.3211) and
+    (393.8715,458.9445) .. (397.8750,460.1250) .. controls (401.8903,461.3605) and
+    (406.3135,461.9688) .. (411.1250,461.9688) .. controls (422.9271,461.9688) and
+    (432.8357,458.8858) .. (440.7500,452.7188) .. controls (448.6732,446.5963) and
+    (452.6875,438.5099) .. (452.6875,428.6250) .. controls (452.6875,423.5424) and
+    (451.8139,419.3245) .. (450.0313,415.9688) .. controls (448.2737,412.6089) and
+    (446.0071,409.8517) .. (443.2500,407.7188) .. controls (440.6098,405.6999) and
+    (437.6168,404.1577) .. (434.3125,403.1250) .. controls (431.2903,402.1656) and
+    (428.4437,401.5684) .. (425.7188,401.2813) -- (425.7188,401.0313) .. controls
+    (429.9462,399.8234) and (433.5316,398.3019) .. (436.3750,396.4063) .. controls
+    (439.3588,394.4000) and (441.7734,392.1633) .. (443.5938,389.7188) .. controls
+    (445.2562,387.4849) and (446.4583,385.0731) .. (447.1875,382.4688) --
+    (447.1875,382.4375) .. controls (447.9098,379.8061) and (448.2812,377.2137) ..
+    (448.2813,374.6250) .. controls (448.2812,372.5132) and (447.8100,370.0304) ..
+    (446.9375,367.1562) .. controls (446.0482,364.2269) and (444.4516,361.4494) ..
+    (442.1250,358.8125) .. controls (439.7295,356.1046) and (436.4304,353.8164) ..
+    (432.2813,351.9688) .. controls (432.2733,351.9647) and (432.2585,351.9728) ..
+    (432.2500,351.9688) .. controls (428.0952,350.0532) and (422.8701,349.0938) ..
+    (416.5938,349.0938) -- cycle(416.5938,350.3125) .. controls
+    (422.7604,350.3126) and (427.8075,351.2392) .. (431.7500,353.0625) .. controls
+    (435.7908,354.8585) and (438.9298,357.0417) .. (441.1875,359.5938) .. controls
+    (443.4178,362.1216) and (444.9489,364.7586) .. (445.7812,367.5000) .. controls
+    (446.6302,370.2969) and (447.0312,372.6862) .. (447.0312,374.6250) .. controls
+    (447.0312,377.0998) and (446.6953,379.5919) .. (446.0000,382.1250) .. controls
+    (445.3114,384.5842) and (444.2030,386.8795) .. (442.6250,389.0000) .. controls
+    (440.9009,391.3151) and (438.5771,393.4320) .. (435.6875,395.3750) .. controls
+    (432.8713,397.2525) and (429.2959,398.7977) .. (424.9375,400.0000) --
+    (424.5000,400.1250) -- (424.5000,400.5938) -- (424.5000,401.8125) --
+    (424.5000,402.3750) -- (425.0312,402.4063) .. controls (427.8151,402.6549) and
+    (430.7833,403.2800) .. (433.9375,404.2813) -- (433.9688,404.2813) .. controls
+    (437.1455,405.2741) and (439.9756,406.7571) .. (442.5000,408.6875) .. controls
+    (445.1100,410.7067) and (447.2519,413.3089) .. (448.9375,416.5313) .. controls
+    (450.5978,419.6567) and (451.4375,423.6822) .. (451.4375,428.6250) .. controls
+    (451.4375,438.1834) and (447.6718,445.8218) .. (440.0000,451.7500) .. controls
+    (432.3192,457.7351) and (422.7156,460.7500) .. (411.1250,460.7500) .. controls
+    (406.4174,460.7500) and (402.1335,460.1325) .. (398.2500,458.9375) --
+    (398.2188,458.9375) .. controls (394.3234,457.7889) and (391.0214,456.2296) ..
+    (388.2500,454.2500) .. controls (385.4806,452.2719) and (383.3338,450.0134) ..
+    (381.8125,447.4688) .. controls (381.8075,447.4598) and (381.8175,447.4462) ..
+    (381.8125,447.4375) .. controls (380.3501,444.8937) and (379.5938,442.2897) ..
+    (379.5938,439.6250) .. controls (379.5938,437.2436) and (380.1884,435.1587) ..
+    (381.3438,433.2812) -- (381.3438,433.2500) .. controls (382.4569,431.3946) and
+    (384.1263,430.5312) .. (386.6562,430.5312) .. controls (389.5925,430.5312) and
+    (391.7280,431.2428) .. (393.1562,432.6250) -- (393.1562,432.6562) .. controls
+    (394.6782,434.0355) and (395.4062,435.5285) .. (395.4062,437.2812) .. controls
+    (395.4062,438.8316) and (395.1445,440.8592) .. (394.5938,443.3125) --
+    (394.5625,443.3125) .. controls (394.0575,445.7868) and (393.6689,447.5649) ..
+    (393.3750,448.5938) -- (393.2812,448.8750) -- (393.4688,449.1250) .. controls
+    (393.8779,449.6511) and (394.5411,450.2582) .. (395.4688,451.0312) --
+    (395.4688,451.0625) .. controls (396.4790,451.8601) and (397.6889,452.5632) ..
+    (399.0938,453.1875) .. controls (400.7490,453.9634) and (402.4733,454.5664) ..
+    (404.2812,455.0313) .. controls (406.1403,455.5093) and (408.6995,455.7500) ..
+    (411.9688,455.7500) .. controls (415.0746,455.7500) and (418.0544,455.2246) ..
+    (420.9062,454.1875) .. controls (423.8297,453.1434) and (426.4054,451.4488) ..
+    (428.5938,449.1563) .. controls (430.8716,446.7748) and (432.6333,443.9792) ..
+    (433.8750,440.7813) .. controls (433.8780,440.7723) and (433.8720,440.7589) ..
+    (433.8750,440.7500) .. controls (435.1781,437.5565) and (435.8124,433.4132) ..
+    (435.8125,428.3125) .. controls (435.8124,425.5331) and (435.4924,422.7896) ..
+    (434.8750,420.0625) .. controls (434.3008,417.2964) and (433.1940,414.8651) ..
+    (431.5625,412.8125) .. controls (429.9186,410.7444) and (427.6914,409.1578) ..
+    (424.8750,408.0625) -- (424.8750,408.0938) .. controls (422.0884,406.9371) and
+    (418.5815,406.3751) .. (414.3750,406.3750) -- (405.0625,406.3750) --
+    (405.0625,398.8438) -- (411.0625,398.8438) .. controls (418.1619,398.8438) and
+    (423.3956,396.8673) .. (426.6250,392.8438) .. controls (429.8388,388.8397) and
+    (431.4062,382.8907) .. (431.4062,375.0625) .. controls (431.4062,368.6374) and
+    (429.8750,363.7121) .. (426.7500,360.3750) .. controls (423.6367,356.9981) and
+    (419.2140,355.3126) .. (413.6250,355.3125) .. controls (410.9412,355.3126) and
+    (408.6935,355.6486) .. (406.8750,356.3438) .. controls (405.1817,356.9596) and
+    (403.7942,357.5864) .. (402.6875,358.2188) .. controls (401.3782,358.9521) and
+    (400.2991,359.7722) .. (399.4375,360.6875) .. controls (398.6294,361.5462) and
+    (398.0210,362.1666) .. (397.6250,362.5625) -- (397.4062,362.8125) --
+    (397.4688,363.1250) .. controls (397.8228,364.7437) and (398.2438,366.7461) ..
+    (398.7500,369.1250) .. controls (399.2481,371.4166) and (399.5000,373.6095) ..
+    (399.5000,375.6875) .. controls (399.5000,377.3850) and (398.7789,378.8793) ..
+    (397.2500,380.3125) .. controls (395.8262,381.6445) and (393.6794,382.3751) ..
+    (390.6875,382.3750) .. controls (388.1498,382.3751) and (386.4382,381.5087) ..
+    (385.2812,379.7500) .. controls (384.1306,377.9283) and (383.5625,375.8403) ..
+    (383.5625,373.4063) .. controls (383.5625,370.8869) and (384.2578,368.3186) ..
+    (385.6875,365.6563) .. controls (387.1119,363.0040) and (389.2257,360.4955) ..
+    (392.0625,358.1563) .. controls (394.8853,355.8288) and (398.3413,353.9488) ..
+    (402.4375,352.5000) .. controls (406.5107,351.0596) and (411.2311,350.3126) ..
+    (416.5938,350.3125) -- cycle;
+\end{tikzpicture}
+}
+
+
+
+\newcommand \explogo{%
+\begin{tikzpicture}[y=0.45pt,x=0.45pt,yscale=-1, inner sep=0pt, outer sep=0pt]
+  \path[fill=black] (188.1546,427.4287) .. controls (190.5345,431.7164) and
+    (193.0099,435.4077) .. (195.5921,438.5850) -- (195.6233,438.6163) .. controls
+    (195.6323,438.6274) and (195.6455,438.6365) .. (195.6545,438.6476) .. controls
+    (194.4650,438.4740) and (193.2397,438.3529) .. (191.9670,438.3663) .. controls
+    (189.4530,438.3928) and (186.7534,438.8247) .. (183.8420,439.7413) .. controls
+    (188.8419,443.9283) and (193.0993,446.9893) .. (196.8420,449.3663) .. controls
+    (196.7505,449.3362) and (196.6520,449.3022) .. (196.5607,449.2726) --
+    (196.8420,449.4289) .. controls (191.0442,447.6143) and (184.7895,447.3923) ..
+    (177.4670,450.8664) .. controls (182.7247,454.1565) and (187.1369,456.5570) ..
+    (191.0295,458.3664) .. controls (190.9155,458.3495) and (190.7995,458.3198) ..
+    (190.6857,458.3039) -- (190.9670,458.4601) .. controls (184.8999,457.4153) and
+    (178.6035,458.0026) .. (171.7482,462.5226) .. controls (176.2179,464.5144) and
+    (180.1011,466.0179) .. (183.5607,467.1789) -- (183.5919,467.1789) --
+    (183.8107,467.3039) .. controls (178.0253,467.5288) and (172.2917,469.3302) ..
+    (166.6857,474.6476) .. controls (171.5829,475.8624) and (175.7757,476.6736) ..
+    (179.4669,477.2101) .. controls (179.3633,477.2310) and (179.2580,477.2503) ..
+    (179.1544,477.2726) .. controls (179.0103,477.2696) and (178.8604,477.2746) ..
+    (178.7169,477.2726) -- (178.8732,477.3351) .. controls (174.5605,478.3144) and
+    (170.3552,480.4767) .. (166.2482,484.6164) .. controls (169.5756,485.3353) and
+    (172.5696,485.8937) .. (175.3107,486.3039) .. controls (171.9361,487.9351) and
+    (168.7309,490.4629) .. (165.8107,494.3351) .. controls (169.6449,494.6328) and
+    (173.0419,494.7600) .. (176.0919,494.7726) .. controls (172.4017,496.4801) and
+    (168.9244,499.1610) .. (165.8419,503.4914) .. controls (171.3184,503.7651) and
+    (175.8960,503.7533) .. (179.8419,503.5226) .. controls (179.7681,503.5528) and
+    (179.6968,503.5855) .. (179.6232,503.6163) .. controls (179.3834,503.6377) and
+    (179.1427,503.6531) .. (178.9044,503.6788) -- (179.2482,503.8038) .. controls
+    (175.1462,505.6048) and (171.3495,508.5232) .. (168.0919,513.4600) .. controls
+    (174.8980,513.5594) and (180.2892,513.2381) .. (184.8107,512.6788) .. controls
+    (184.6730,512.7162) and (184.5417,512.7645) .. (184.4044,512.8038) .. controls
+    (184.2299,512.8144) and (184.0455,512.8223) .. (183.8732,512.8350) --
+    (184.0919,512.8975) .. controls (178.7598,514.4860) and (173.8363,517.5457) ..
+    (169.7482,523.7412) .. controls (175.2461,523.8214) and (179.8367,523.6133) ..
+    (183.7794,523.2412) .. controls (183.6938,523.2879) and (183.6146,523.3500) ..
+    (183.5294,523.3975) .. controls (178.8190,526.0253) and (174.7697,529.9721) ..
+    (172.0919,536.6475) .. controls (176.9272,535.7317) and (180.9801,534.7653) ..
+    (184.4982,533.7412) .. controls (184.4398,533.7875) and (184.3686,533.8191) ..
+    (184.3107,533.8662) -- (184.5294,533.8350) .. controls (180.9081,536.5374) and
+    (177.8636,540.3240) .. (175.8107,545.9288) .. controls (179.1397,545.1929) and
+    (182.1140,544.4194) .. (184.7794,543.6475) .. controls (182.3867,546.5404) and
+    (180.5386,550.1515) .. (179.4982,554.8975) .. controls (183.1131,553.5663) and
+    (186.2487,552.2854) .. (189.0294,551.0225) .. controls (188.9958,551.0619) and
+    (188.9691,551.1079) .. (188.9357,551.1475) .. controls (188.8789,551.1923) and
+    (188.8034,551.2277) .. (188.7482,551.2725) -- (188.8419,551.2413) .. controls
+    (186.2910,554.2981) and (184.3447,558.1421) .. (183.3732,563.2413) .. controls
+    (188.4628,561.2062) and (192.6027,559.2529) .. (196.0919,557.3976) .. controls
+    (195.9933,557.4930) and (195.8722,557.5825) .. (195.7794,557.6788) --
+    (195.8731,557.6476) .. controls (192.7873,561.0321) and (190.4833,565.3800) ..
+    (189.5606,571.3664) .. controls (195.5682,568.7142) and (200.1972,566.2494) ..
+    (203.9981,563.9289) .. controls (203.9580,563.9700) and (203.9127,564.0127) ..
+    (203.8731,564.0539) -- (204.1231,563.9289) .. controls (199.8075,567.6248) and
+    (196.4969,572.5288) .. (195.3419,580.0226) .. controls (203.4387,576.4482) and
+    (209.1016,573.2112) .. (213.4981,570.2101) .. controls (211.6101,574.0286) and
+    (210.6125,578.4777) .. (211.0919,584.0539) .. controls (218.9172,578.0502) and
+    (223.8713,573.2098) .. (227.5606,568.9289) .. controls (227.5546,568.9906) and
+    (227.5656,569.0545) .. (227.5606,569.1164) .. controls (227.3369,571.8296) and
+    (227.5060,574.7714) .. (228.3106,578.0226) .. controls (232.9500,570.0520) and
+    (237.5899,566.7480) .. (242.3106,564.0226) .. controls (236.4069,567.8493) and
+    (237.4669,570.9503) .. (237.4669,574.4914) .. controls (244.4870,567.0983) and
+    (254.2537,559.2459) .. (257.2481,554.3351) .. controls (253.2445,560.3478) and
+    (251.6457,566.0579) .. (250.5919,571.0851) .. controls (230.1065,581.9187) and
+    (217.6060,584.7541) .. (203.6231,589.0851) .. controls (209.0471,591.0745) and
+    (214.8691,593.0070) .. (212.4669,595.7726) -- (206.0606,602.1789) .. controls
+    (210.1567,600.9056) and (214.3405,599.0697) .. (217.9669,601.5539) .. controls
+    (217.6110,604.9137) and (213.3733,606.6264) .. (209.7481,608.5851) .. controls
+    (216.1304,606.2854) and (217.5075,606.8270) .. (219.1856,607.3664) .. controls
+    (220.0240,611.3923) and (217.1123,613.5511) .. (215.2169,616.2101) .. controls
+    (231.2927,603.9867) and (252.2574,594.3357) .. (267.0294,590.3039) .. controls
+    (287.8076,583.3065) and (314.6175,576.0122) .. (321.9044,558.2726) --
+    (329.1856,529.0226) .. controls (337.7280,519.7775) and (345.5838,510.2065) ..
+    (349.3108,498.5539) .. controls (373.0973,493.9520) and (392.3393,495.6016) ..
+    (412.4046,496.1164) .. controls (410.5758,495.8116) and (351.1546,485.7414) ..
+    (351.1546,485.7414) .. controls (333.7856,461.9756) and (307.8721,478.1391) ..
+    (299.3421,501.6164) .. controls (297.1891,507.5420) and (284.9022,507.5289) ..
+    (281.3421,501.5852) .. controls (267.2670,471.2820) and (224.5286,439.2367) ..
+    (188.1546,427.4289) -- cycle;
+  \path[fill=basecolor] (187.7346,425.7215) .. controls (190.1312,430.0392) and
+    (192.6231,433.7232) .. (195.2248,436.9158) .. controls (194.0353,436.7423) and
+    (192.8098,436.6402) .. (191.5371,436.6536) .. controls (189.0231,436.6801) and
+    (186.3356,437.0974) .. (183.4241,438.0140) .. controls (188.5047,442.2685) and
+    (192.7982,445.3733) .. (196.5852,447.7660) .. controls (190.7343,445.8972) and
+    (184.4338,445.6311) .. (177.0321,449.1427) .. controls (182.4382,452.5257) and
+    (186.9760,454.9705) .. (190.9471,456.7968) .. controls (184.7555,455.6556) and
+    (178.3356,456.1756) .. (171.3284,460.7959) .. controls (175.9548,462.8576) and
+    (179.9558,464.4054) .. (183.5061,465.5818) .. controls (177.6784,465.7855) and
+    (171.9101,467.5854) .. (166.2639,472.9408) .. controls (171.1611,474.1557) and
+    (175.3568,474.9612) .. (179.0480,475.4977) .. controls (174.5307,476.4104) and
+    (170.0996,478.5772) .. (165.8050,482.9059) .. controls (169.1324,483.6248) and
+    (172.1275,484.1674) .. (174.8686,484.5777) .. controls (171.4940,486.2088) and
+    (168.2990,488.7365) .. (165.3788,492.6087) .. controls (169.2130,492.9064) and
+    (172.6053,493.0386) .. (175.6553,493.0512) .. controls (171.9650,494.7587) and
+    (168.5104,497.4567) .. (165.4280,501.7871) .. controls (170.9044,502.0608) and
+    (175.4790,502.0342) .. (179.4250,501.8034) .. controls (175.0884,503.5763) and
+    (171.0915,506.5720) .. (167.6734,511.7521) .. controls (174.4795,511.8515) and
+    (179.8697,511.5247) .. (184.3911,510.9654) .. controls (178.7800,512.4888) and
+    (173.5859,515.5521) .. (169.3124,522.0286) .. controls (174.8103,522.1088) and
+    (179.3994,521.9089) .. (183.3421,521.5369) .. controls (178.5221,524.1635) and
+    (174.3823,528.1477) .. (171.6562,534.9438) .. controls (176.6186,534.0040) and
+    (180.7774,532.9979) .. (184.3583,531.9445) .. controls (180.6281,534.6591) and
+    (177.4926,538.4719) .. (175.3930,544.2041) .. controls (178.7220,543.4682) and
+    (181.6765,542.6978) .. (184.3419,541.9259) .. controls (181.9491,544.8188) and
+    (180.1048,548.4397) .. (179.0644,553.1858) .. controls (182.6793,551.8545) and
+    (185.8062,550.5643) .. (188.5869,549.3014) .. controls (185.9451,552.3928) and
+    (183.9273,556.3063) .. (182.9324,561.5282) .. controls (188.0220,559.4931) and
+    (192.1617,557.5487) .. (195.6510,555.6934) .. controls (192.4524,559.1128) and
+    (190.0726,563.5113) .. (189.1278,569.6412) .. controls (195.3243,566.9057) and
+    (200.0785,564.3715) .. (203.9442,561.9871) .. controls (199.5047,565.7077) and
+    (196.0910,570.6550) .. (194.9134,578.2951) .. controls (203.0102,574.7206) and
+    (208.6604,571.4786) .. (213.0570,568.4775) .. controls (211.1690,572.2961) and
+    (210.1683,576.7672) .. (210.6477,582.3434) .. controls (218.4730,576.3397) and
+    (223.4302,571.4800) .. (227.1195,567.1991) .. controls (226.8707,569.9634) and
+    (227.0669,572.9701) .. (227.8899,576.2955) .. controls (233.5078,566.6437) and
+    (239.0905,563.8256) .. (244.8678,560.6045) .. controls (235.6654,565.2375) and
+    (237.0296,568.7253) .. (237.0296,572.7723) .. controls (244.0497,565.3793) and
+    (253.8400,557.5393) .. (256.8344,552.6285) .. controls (252.8308,558.6412) and
+    (251.2011,564.3353) .. (250.1474,569.3626) .. controls (229.6620,580.1962) and
+    (217.1896,583.0276) .. (203.2067,587.3587) .. controls (208.6306,589.3481) and
+    (214.4431,591.2965) .. (212.0409,594.0622) -- (205.6324,600.4542) .. controls
+    (209.7285,599.1810) and (213.9051,597.3636) .. (217.5315,599.8478) .. controls
+    (217.1756,603.2077) and (212.9289,604.9040) .. (209.3037,606.8627) .. controls
+    (215.6860,604.5630) and (217.0662,605.0941) .. (218.7443,605.6335) .. controls
+    (219.5827,609.6594) and (216.6733,611.8250) .. (214.7780,614.4840) .. controls
+    (230.8537,602.2606) and (251.8308,592.6034) .. (266.6028,588.5716) .. controls
+    (287.3810,581.5741) and (314.1729,574.3016) .. (321.4598,556.5621) --
+    (328.7697,527.3061) .. controls (337.3119,518.0610) and (345.1694,508.4736) ..
+    (348.8965,496.8210) .. controls (372.6829,492.2191) and (391.9159,493.8805) ..
+    (411.9812,494.3952) .. controls (410.1524,494.0905) and (350.7157,484.0204) ..
+    (350.7157,484.0204) .. controls (333.3467,460.2547) and (307.4537,476.4086) ..
+    (298.9237,499.8859) .. controls (296.7707,505.8115) and (284.4877,505.8133) ..
+    (280.9276,499.8695) .. controls (266.8525,469.5663) and (224.1086,437.5293) ..
+    (187.7346,425.7216) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (328.0690,487.7425) -- (327.9127,487.9925) .. controls (327.2963,489.1409) and
+    (326.2537,489.9248) .. (324.7877,490.3988) .. controls (323.3218,490.8728) and
+    (321.4437,491.0247) .. (319.2565,490.9300) -- (317.8815,490.8675) --
+    (318.8815,491.8363) .. controls (319.3892,492.3246) and (319.5310,492.7144) ..
+    (319.5377,493.0550) .. controls (319.5447,493.3957) and (319.3983,493.7636) ..
+    (319.0690,494.1800) .. controls (318.4103,495.0130) and (317.1020,495.9174) ..
+    (315.8815,496.8363) -- (315.4752,497.1175) -- (315.7565,497.5238) .. controls
+    (316.7747,499.0858) and (317.2409,500.2883) .. (317.3502,501.2113) .. controls
+    (317.4595,502.1343) and (317.2450,502.7963) .. (316.8190,503.3675) .. controls
+    (315.9669,504.5101) and (314.0965,505.2843) .. (312.4127,506.2425) --
+    (312.1002,506.3988) -- (312.1627,506.7738) .. controls (312.3075,507.6524) and
+    (312.0708,508.3704) .. (311.4440,509.0863) .. controls (310.8171,509.8021) and
+    (309.7619,510.4847) .. (308.3502,511.0863) -- (307.9752,511.2425) --
+    (308.0377,511.6488) .. controls (308.3193,513.5300) and (308.8848,515.1671) ..
+    (310.0690,516.2113) .. controls (311.1523,517.1665) and (312.7911,517.4184) ..
+    (314.8815,516.9925) .. controls (315.2459,518.9979) and (315.7682,520.8217) ..
+    (316.9752,522.0238) .. controls (318.1986,523.2421) and (320.1355,523.6024) ..
+    (322.7252,522.9300) .. controls (323.3080,524.3346) and (324.1596,525.3355) ..
+    (325.1315,525.9925) .. controls (326.1986,526.7139) and (327.5930,527.0049) ..
+    (328.7401,527.3612) -- (329.4197,526.6303) .. controls (328.2812,526.2767) and
+    (326.6004,525.7302) .. (325.6940,525.1175) .. controls (324.7876,524.5048) and
+    (324.0512,523.6643) .. (323.5377,522.2113) -- (323.3815,521.7113) --
+    (322.8815,521.8675) .. controls (320.2185,522.6859) and (318.7418,522.3174) ..
+    (317.7252,521.3050) .. controls (316.7087,520.2927) and (316.1370,518.4626) ..
+    (315.7877,516.3363) -- (315.6940,515.7738) -- (315.1315,515.9300) .. controls
+    (312.9366,516.5027) and (311.6408,516.2098) .. (310.7565,515.4300) .. controls
+    (309.9304,514.7016) and (309.4415,513.4103) .. (309.1628,511.8050) .. controls
+    (310.4344,511.2171) and (311.5245,510.5741) .. (312.2253,509.7738) .. controls
+    (312.9099,508.9919) and (313.2063,508.0267) .. (313.1628,507.0238) .. controls
+    (314.7142,506.1705) and (316.5854,505.4372) .. (317.6628,503.9925) .. controls
+    (318.2261,503.2372) and (318.5187,502.2444) .. (318.3815,501.0863) .. controls
+    (318.2568,500.0326) and (317.7408,498.8152) .. (316.8503,497.3675) .. controls
+    (317.9434,496.5623) and (319.1300,495.7554) .. (319.8815,494.8050) .. controls
+    (320.2994,494.2767) and (320.6136,493.6919) .. (320.6003,493.0238) .. controls
+    (320.5933,492.6554) and (320.2387,492.3198) .. (320.0378,491.9613) .. controls
+    (321.9389,491.9861) and (323.6709,491.8609) .. (325.1003,491.3988) .. controls
+    (326.6062,490.9119) and (327.7892,490.0245) .. (328.5690,488.8050) .. controls
+    (330.8191,488.8168) and (333.1492,489.3112) .. (335.5065,489.6175) .. controls
+    (337.9280,489.9322) and (340.3922,490.0166) .. (342.7253,488.9925) --
+    (342.2878,488.0238) .. controls (340.2235,488.9299) and (338.0183,488.8923) ..
+    (335.6628,488.5863) .. controls (333.3073,488.2802) and (330.8524,487.7246) ..
+    (328.3815,487.7425) -- cycle;
+  \path[draw=white,fill=white,miter limit=4.00,line width=0.839pt]
+    (336.8186,487.3469) .. controls (336.8186,489.7993) and (334.8306,491.7873) ..
+    (332.3782,491.7873) .. controls (329.9259,491.7873) and (327.9379,489.7993) ..
+    (327.9379,487.3469) .. controls (327.9379,484.8946) and (329.9259,482.9065) ..
+    (332.3782,482.9065) .. controls (334.8306,482.9065) and (336.8186,484.8945) ..
+    (336.8186,487.3469) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (350.0784,483.1829) .. controls (346.0920,488.3688) and (345.0896,487.0295) ..
+    (342.6627,487.8988) -- (342.2565,488.0550) -- (342.3190,488.4925) .. controls
+    (343.2534,493.7013) and (346.3404,495.3564) .. (348.7497,497.2498) --
+    (348.8842,496.8285) -- (349.5255,496.7063) .. controls (347.1103,494.8083) and
+    (344.4675,493.2007) .. (343.5065,488.7738) .. controls (345.2738,488.3557) and
+    (346.9603,488.8903) .. (350.7252,483.9925) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (196.5832,447.7548) .. controls (204.1159,452.4256) and (216.5138,457.2421) ..
+    (224.4752,462.2738) .. controls (228.8554,465.0628) and (232.7896,467.8418) ..
+    (235.8502,470.2425) .. controls (238.9108,472.6433) and (241.1740,475.1236) ..
+    (242.0065,475.9300) .. controls (242.8390,476.7364) and (243.4041,476.3554) ..
+    (242.8502,475.3050) .. controls (242.2964,474.2547) and (239.5701,471.8264) ..
+    (236.4752,469.3988) .. controls (233.3804,466.9712) and (229.4438,464.2043) ..
+    (225.0377,461.3988) .. controls (216.2255,455.7878) and (205.8833,450.7708) ..
+    (196.5832,447.7548) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (195.2242,436.9074) .. controls (198.3819,437.6366) and (203.0426,440.3298) ..
+    (208.2252,443.2113) .. controls (213.4079,446.0928) and (219.0564,449.6386) ..
+    (224.2252,453.0863) .. controls (229.3940,456.5340) and (233.3791,459.5515) ..
+    (236.5649,461.9823) .. controls (239.5902,464.5711) and (241.0838,466.2475) ..
+    (241.6627,466.2425) .. controls (241.7421,466.2585) and (241.8203,466.2597) ..
+    (241.9440,466.2425) .. controls (242.0677,466.2253) and (242.2764,466.1299) ..
+    (242.3815,465.9300) .. controls (242.4865,465.7302) and (242.4459,465.5623) ..
+    (242.4128,465.4613) .. controls (242.3796,465.3603) and (242.3618,465.3067) ..
+    (242.3191,465.2425) .. controls (242.1482,464.9858) and (241.8873,464.7454) ..
+    (241.5066,464.3988) .. controls (240.7451,463.7056) and (239.4870,462.6862) ..
+    (237.8816,461.4613) .. controls (234.6708,459.0114) and (230.0051,455.6705) ..
+    (224.8191,452.2113) .. controls (219.6331,448.7521) and (213.9447,445.1757) ..
+    (208.7253,442.2738) .. controls (206.8700,441.5863) and (197.7714,436.7746) ..
+    (195.2243,436.9074) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (190.9046,456.7968) .. controls (200.5728,460.7431) and (214.3261,465.3785) ..
+    (223.5065,471.1488) .. controls (228.4392,474.2811) and (232.7356,477.4014) ..
+    (235.9440,479.9613) .. controls (237.5482,481.2412) and (238.8881,482.3917) ..
+    (239.8815,483.3050) .. controls (240.8749,484.2184) and (241.4352,485.0475) ..
+    (241.7565,485.2738) .. controls (242.4289,485.7475) and (242.9436,485.4328) ..
+    (242.6315,484.6800) .. controls (242.3958,484.1116) and (241.6181,483.4596) ..
+    (240.6002,482.5238) .. controls (239.5823,481.5880) and (238.2198,480.4410) ..
+    (236.6002,479.1488) .. controls (233.3611,476.5644) and (229.0363,473.3968) ..
+    (224.0690,470.2425) .. controls (214.1344,463.9341) and (202.2573,458.3877) ..
+    (190.9046,456.7968) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (183.4711,465.5716) .. controls (191.0060,465.5766) and (206.5713,472.4735) ..
+    (213.1315,475.9300) .. controls (223.7689,481.6031) and (233.4415,488.8954) ..
+    (238.7877,493.9925) .. controls (239.3805,494.5577) and (240.2465,494.0588) ..
+    (239.5690,493.2738) .. controls (234.6033,487.5198) and (224.3477,480.7388) ..
+    (213.6315,475.0238) .. controls (202.9153,469.3087) and (191.8189,465.5632) ..
+    (183.4711,465.5716) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (179.1133,475.4956) .. controls (190.4411,477.1531) and (204.0196,481.7255) ..
+    (213.9127,486.6800) .. controls (219.4336,489.4832) and (224.3566,492.4856) ..
+    (228.1315,495.1488) .. controls (231.9064,497.8120) and (234.6937,500.8104) ..
+    (235.3815,501.5863) .. controls (236.0693,502.3622) and (236.8886,502.3945) ..
+    (236.2565,501.0238) .. controls (235.6244,499.6531) and (232.5499,496.9721) ..
+    (228.7252,494.2738) .. controls (224.9006,491.5755) and (219.9456,488.5676) ..
+    (214.3815,485.7425) .. controls (203.2533,480.0924) and (190.5800,475.6473) ..
+    (179.1133,475.4956) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (182.8502,483.9300) .. controls (180.0362,483.6845) and (177.5032,484.2615) ..
+    (174.9224,484.5841) .. controls (184.9876,483.6409) and (199.0622,488.2631) ..
+    (208.4440,492.5863) .. controls (219.4960,497.7676) and (228.6734,504.8810) ..
+    (233.0690,509.3988) .. controls (233.7572,510.1061) and (234.2435,509.2048) ..
+    (233.8815,508.7425) .. controls (229.7881,503.5164) and (220.0397,496.8487) ..
+    (208.8815,491.6175) .. controls (200.5128,487.6942) and (191.2924,484.6668) ..
+    (182.8502,483.9300) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (175.7074,492.9973) .. controls (185.6124,493.7315) and (198.8738,496.1032) ..
+    (208.1627,500.3675) .. controls (217.5053,504.7372) and (224.5953,510.4032) ..
+    (228.1627,513.6175) .. controls (228.7116,514.1121) and (229.6823,513.7617) ..
+    (228.9127,512.8675) .. controls (225.6572,509.0849) and (218.0877,503.8529) ..
+    (208.6315,499.4300) .. controls (199.1753,495.0072) and (187.6892,492.1744) ..
+    (175.7074,492.9973) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (184.6002,501.2425) .. controls (182.5105,501.1718) and (181.5301,501.5628) ..
+    (179.5141,501.7805) .. controls (186.2367,502.0768) and (196.9195,503.8647) ..
+    (202.8190,505.8675) .. controls (210.4747,508.5236) and (216.7699,512.5245) ..
+    (220.3502,515.6488) .. controls (221.0416,516.2521) and (221.5570,515.4427) ..
+    (221.1002,514.9300) .. controls (217.7467,511.1667) and (210.9312,507.5627) ..
+    (203.1627,504.8675) .. controls (197.3364,502.8461) and (190.8693,501.4545) ..
+    (184.6002,501.2425) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (184.3157,510.9926) .. controls (198.6871,511.9623) and (207.3770,514.4944) ..
+    (214.0377,520.4613) .. controls (214.5368,520.9084) and (215.3247,520.2930) ..
+    (214.7877,519.7113) .. controls (207.9520,512.3054) and (194.4933,510.2417) ..
+    (184.3157,510.9926) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (195.3815,519.6175) .. controls (191.0251,519.2671) and (187.3797,520.2191) ..
+    (183.4094,521.5412) .. controls (195.0282,519.6893) and (199.8590,520.5773) ..
+    (208.6627,524.7113) .. controls (209.6662,525.1825) and (209.6073,524.0723) ..
+    (209.1627,523.8050) .. controls (204.4864,520.9942) and (199.7378,519.9679) ..
+    (195.3815,519.6175) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (194.9584,527.7065) .. controls (190.8394,528.0717) and (187.3420,529.4861) ..
+    (184.4584,531.8315) .. controls (195.9645,527.3967) and (199.1447,528.2791) ..
+    (207.9440,530.7738) .. controls (209.1013,531.1019) and (208.7417,529.9871) ..
+    (208.2877,529.8050) .. controls (203.0183,527.6924) and (199.0774,527.3413) ..
+    (194.9584,527.7065) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (217.7565,534.8363) .. controls (211.6177,534.1725) and (204.7011,534.9170) ..
+    (198.6315,536.0238) .. controls (192.5618,537.1306) and (187.3415,539.3794) ..
+    (184.3947,541.7762) .. controls (194.4866,537.5140) and (196.3258,537.5231) ..
+    (198.8190,537.0550) .. controls (204.7989,535.9646) and (210.7264,535.5394) ..
+    (217.6940,535.8675) .. controls (218.3258,535.8973) and (218.2935,534.8944) ..
+    (217.7565,534.8363) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (221.3190,539.8050) .. controls (214.6662,539.5537) and (207.7944,541.2000) ..
+    (201.8502,542.8988) .. controls (195.9061,544.5976) and (191.4940,546.9158) ..
+    (188.5846,549.2822) .. controls (194.4716,546.4504) and (199.9499,544.5335) ..
+    (202.1315,543.8988) .. controls (207.9926,542.2237) and (213.9052,540.7736) ..
+    (221.3815,540.8675) .. controls (221.9623,540.8745) and (222.3377,539.8435) ..
+    (221.3190,539.8050) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (226.7565,543.8988) .. controls (220.4907,544.8239) and (213.9208,546.6745) ..
+    (208.1940,548.6175) .. controls (202.4671,550.5606) and (198.3906,552.8682) ..
+    (195.7313,555.6308) .. controls (202.5433,551.7206) and (206.2895,550.3495) ..
+    (208.5065,549.5863) .. controls (214.1631,547.6670) and (219.4450,546.3315) ..
+    (226.9440,544.9300) .. controls (227.8440,544.7618) and (227.1212,543.8449) ..
+    (226.7565,543.8988) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (229.9440,549.1175) .. controls (217.3782,551.1190) and (209.2362,556.5404) ..
+    (204.0606,561.9168) .. controls (212.0814,555.8737) and (217.6610,552.6260) ..
+    (230.1627,550.1488) .. controls (230.9540,549.9920) and (230.7150,548.9947) ..
+    (229.9440,549.1175) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (236.0690,553.7113) .. controls (223.4309,555.6581) and (216.1430,563.3408) ..
+    (213.1075,568.4120) .. controls (221.1036,560.4242) and (227.3269,556.0769) ..
+    (236.2877,554.7425) .. controls (237.1946,554.6075) and (236.9632,553.5735) ..
+    (236.0690,553.7113) -- cycle;
+  \path[color=black,fill=white,nonzero rule,line width=0.839pt]
+    (239.8815,557.7113) .. controls (237.9104,557.9574) and (235.2282,559.3533) ..
+    (232.6940,560.9613) .. controls (230.1598,562.5693) and (228.2477,564.5258) ..
+    (227.1075,567.0466) .. controls (230.1601,563.8962) and (231.3821,563.0437) ..
+    (233.2565,561.8363) .. controls (235.6896,560.2924) and (238.1414,559.3201) ..
+    (240.1315,558.7425) .. controls (241.0644,558.4718) and (240.3594,557.6516) ..
+    (239.8815,557.7113) -- cycle;
+  \path[draw=white,fill=white,miter limit=4.00,line width=0.839pt]
+    (336.8186,487.3469) .. controls (336.8186,489.7993) and (334.8306,491.7873) ..
+    (332.3782,491.7873) .. controls (329.9259,491.7873) and (327.9379,489.7993) ..
+    (327.9379,487.3469) .. controls (327.9379,484.8946) and (329.9259,482.9065) ..
+    (332.3782,482.9065) .. controls (334.8306,482.9065) and (336.8186,484.8945) ..
+    (336.8186,487.3469) -- cycle;
+  \path[draw=white,fill=maincolor,miter limit=4.00,line width=0.839pt]
+    (336.8186,487.3469) .. controls (336.8186,489.7993) and (334.8306,491.7873) ..
+    (332.3782,491.7873) .. controls (329.9259,491.7873) and (327.9379,489.7993) ..
+    (327.9379,487.3469) .. controls (327.9379,484.8946) and (329.9259,482.9065) ..
+    (332.3782,482.9065) .. controls (334.8306,482.9065) and (336.8186,484.8945) ..
+    (336.8186,487.3469) -- cycle;
+  \path[fill=black] (240.9977,587.6605) .. controls (237.8583,593.6353) and
+    (233.6558,598.3948) .. (228.3899,601.9391) .. controls (223.1240,605.4835) and
+    (217.0733,607.2556) .. (210.2379,607.2556) .. controls (204.2124,607.2556) and
+    (198.9212,606.1923) .. (194.3643,604.0657) .. controls (189.8579,601.9391) and
+    (186.1363,599.0530) .. (183.1996,595.4074) .. controls (180.2628,591.7618) and
+    (178.0603,587.5086) .. (176.5919,582.6478) .. controls (175.1742,577.7870) and
+    (174.4653,572.6477) .. (174.4653,567.2299) .. controls (174.4653,562.3691) and
+    (175.2248,557.6096) .. (176.7438,552.9512) .. controls (178.3134,548.2424) and
+    (180.5919,544.0145) .. (183.5793,540.2676) .. controls (186.4654,536.6727) and
+    (190.0351,533.7866) .. (194.2883,531.6092) .. controls (198.5921,529.3814) and
+    (203.4023,528.2675) .. (208.7188,528.2674) .. controls (214.1872,528.2675) and
+    (218.8708,529.1283) .. (222.7696,530.8497) .. controls (226.6684,532.5713) and
+    (229.8329,534.9258) .. (232.2634,537.9131) .. controls (234.5925,540.7486) and
+    (236.3140,544.0905) .. (237.4280,547.9385) .. controls (238.5925,551.7867) and
+    (239.1748,555.9640) .. (239.1749,560.4703) -- (239.1749,565.4830) --
+    (189.5794,565.4830) .. controls (189.5794,570.3945) and (190.0351,574.8503) ..
+    (190.9465,578.8503) .. controls (191.9085,582.8503) and (193.4022,586.3694) ..
+    (195.4276,589.4073) .. controls (197.4022,592.3441) and (199.9845,594.6732) ..
+    (203.1745,596.3948) .. controls (206.3644,598.0657) and (210.1619,598.9011) ..
+    (214.5670,598.9011) .. controls (219.0733,598.9011) and (222.9468,597.8631) ..
+    (226.1874,595.7872) .. controls (229.4785,593.6606) and (232.6431,589.8631) ..
+    (235.6812,584.3946) -- (240.9977,587.6605)(224.2127,559.1032) .. controls
+    (224.2126,556.2678) and (223.9595,553.2298) .. (223.4532,549.9892) .. controls
+    (222.9974,546.7487) and (222.2379,544.0398) .. (221.1747,541.8625) .. controls
+    (220.0101,539.5334) and (218.4151,537.6347) .. (216.3898,536.1663) .. controls
+    (214.3644,534.6980) and (211.7568,533.9638) .. (208.5669,533.9637) .. controls
+    (203.2504,533.9638) and (198.8200,536.1916) .. (195.2757,540.6473) .. controls
+    (191.7819,545.0525) and (189.8832,551.2044) .. (189.5794,559.1032) --
+    (224.2127,559.1032);
+  \path[fill=black] (321.9606,605.2809) -- (287.6311,605.2809) --
+    (287.6311,600.2682) .. controls (289.9096,600.0151) and (291.8336,599.7619) ..
+    (293.4033,599.5087) .. controls (295.0236,599.2556) and (295.8337,598.5973) ..
+    (295.8337,597.5340) .. controls (295.8337,597.0783) and (295.5805,596.3695) ..
+    (295.0742,595.4074) .. controls (294.5679,594.4454) and (294.0615,593.5593) ..
+    (293.5552,592.7492) .. controls (292.2893,590.7745) and (290.5425,588.1415) ..
+    (288.3147,584.8503) .. controls (286.1374,581.5086) and (283.4538,577.5338) ..
+    (280.2639,572.9262) .. controls (277.6310,576.2174) and (275.2006,579.4326) ..
+    (272.9727,582.5718) .. controls (270.7448,585.6605) and (268.4157,588.9517) ..
+    (265.9853,592.4454) .. controls (265.6309,592.9517) and (265.2511,593.5846) ..
+    (264.8460,594.3441) .. controls (264.4916,595.1036) and (264.3144,595.7112) ..
+    (264.3144,596.1669) .. controls (264.3144,597.2809) and (265.0232,598.2176) ..
+    (266.4410,598.9771) .. controls (267.9093,599.6860) and (270.0866,600.1670) ..
+    (272.9727,600.4201) -- (272.9727,605.2809) -- (245.2509,605.2809) --
+    (245.2509,600.5720) .. controls (248.6940,599.5594) and (251.4535,598.3442) ..
+    (253.5295,596.9264) .. controls (255.6561,595.4581) and (257.6054,593.6606) ..
+    (259.3776,591.5340) .. controls (260.9472,589.5086) and (263.1245,586.7238) ..
+    (265.9093,583.1794) .. controls (268.7448,579.6351) and (272.3904,574.8249) ..
+    (276.8462,568.7489) .. controls (274.2638,565.0527) and (271.0993,560.5463) ..
+    (267.3524,555.2298) .. controls (263.6561,549.8627) and (260.5928,545.4069) ..
+    (258.1624,541.8625) .. controls (256.8459,539.9385) and (255.3269,538.3942) ..
+    (253.6054,537.2296) .. controls (251.9345,536.0144) and (249.5547,535.4068) ..
+    (246.4661,535.4068) -- (246.4661,530.3940) -- (279.0487,530.3940) --
+    (279.0487,535.4068) .. controls (277.4284,535.4068) and (275.8335,535.5081) ..
+    (274.2639,535.7106) .. controls (272.6942,535.9132) and (271.9094,536.3689) ..
+    (271.9094,537.0777) .. controls (271.9094,537.5334) and (272.0613,538.0398) ..
+    (272.3651,538.5967) .. controls (272.6689,539.1537) and (273.0486,539.7613) ..
+    (273.5044,540.4195) .. controls (274.6183,542.1411) and (276.3398,544.7993) ..
+    (278.6690,548.3942) .. controls (281.0487,551.9893) and (283.6057,555.7868) ..
+    (286.3400,559.7868) .. controls (288.1121,557.3564) and (290.1627,554.5209) ..
+    (292.4919,551.2803) .. controls (294.8716,548.0399) and (297.0489,544.9512) ..
+    (299.0236,542.0144) .. controls (299.2261,541.6600) and (299.4286,541.2297) ..
+    (299.6312,540.7233) .. controls (299.8337,540.1664) and (299.9350,539.6347) ..
+    (299.9350,539.1283) .. controls (299.9350,538.0651) and (299.0489,537.2296) ..
+    (297.2768,536.6220) .. controls (295.5552,535.9638) and (293.9096,535.5081) ..
+    (292.3400,535.2549) -- (292.3400,530.3940) -- (319.9859,530.3940) --
+    (319.9859,535.1030) .. controls (316.0870,536.1157) and (313.0490,537.3309) ..
+    (310.8719,538.7486) .. controls (308.6946,540.1157) and (306.8464,541.7107) ..
+    (305.3275,543.5334) .. controls (303.6565,545.6095) and (301.6565,548.1664) ..
+    (299.3274,551.2044) .. controls (297.0489,554.2425) and (293.8337,558.4957) ..
+    (289.6818,563.9640) .. controls (294.2894,570.4451) and (298.0362,575.7617) ..
+    (300.9224,579.9136) .. controls (303.8084,584.0655) and (306.7199,588.3441) ..
+    (309.6567,592.7492) .. controls (311.1250,594.9770) and (312.7452,596.7492) ..
+    (314.5175,598.0657) .. controls (316.3402,599.3315) and (318.8212,600.0657) ..
+    (321.9606,600.2682) -- (321.9606,605.2809);
+  \path[fill=black] (396.9235,539.2802) .. controls (399.9107,542.8246) and
+    (402.2146,546.9512) .. (403.8349,551.6601) .. controls (405.5057,556.3184) and
+    (406.3412,561.6602) .. (406.3413,567.6856) .. controls (406.3412,573.6097) and
+    (405.3538,579.0275) .. (403.3792,583.9389) .. controls (401.4044,588.7998) and
+    (398.7968,592.9517) .. (395.5563,596.3948) .. controls (392.1638,599.8885) and
+    (388.3916,602.5721) .. (384.2398,604.4455) .. controls (380.0878,606.3189) and
+    (375.6826,607.2556) .. (371.0244,607.2556) .. controls (366.5180,607.2556) and
+    (362.8218,606.7493) .. (359.9357,605.7366) .. controls (357.0495,604.7240) and
+    (354.6951,603.5341) .. (352.8723,602.1670) -- (352.2647,602.1670) --
+    (352.2647,624.6482) .. controls (352.2647,626.4710) and (352.6191,627.9900) ..
+    (353.3280,629.2053) .. controls (354.0369,630.4204) and (355.1255,631.3065) ..
+    (356.5939,631.8635) .. controls (357.8090,632.3192) and (359.5306,632.7496) ..
+    (361.7585,633.1547) .. controls (364.0370,633.6103) and (365.9104,633.8635) ..
+    (367.3788,633.9142) -- (367.3788,639.0028) -- (325.5302,639.0028) --
+    (325.5302,633.9142) .. controls (327.0999,633.8129) and (328.6189,633.6863) ..
+    (330.0873,633.5344) .. controls (331.5556,633.3825) and (332.8721,633.1293) ..
+    (334.0367,632.7749) .. controls (335.5557,632.2686) and (336.6190,631.3825) ..
+    (337.2266,630.1167) .. controls (337.8342,628.8508) and (338.1380,627.3571) ..
+    (338.1380,625.6356) -- (338.1380,545.9638) .. controls (338.1380,544.4449) and
+    (337.7582,542.9765) .. (336.9987,541.5587) .. controls (336.2392,540.1410) and
+    (335.2519,539.0018) .. (334.0367,538.1410) .. controls (333.1253,537.5334) and
+    (331.8594,537.0777) .. (330.2392,536.7739) .. controls (328.6189,536.4195) and
+    (327.0492,536.1916) .. (325.5302,536.0903) -- (325.5302,531.1535) --
+    (351.0495,529.4826) -- (352.1128,530.3940) -- (352.1128,538.8245) --
+    (352.7204,538.9764) .. controls (355.3533,535.9385) and (358.6192,533.4068) ..
+    (362.5180,531.3814) .. controls (366.4167,529.3561) and (370.2902,528.3435) ..
+    (374.1384,528.3434) .. controls (378.7966,528.3435) and (383.0498,529.3308) ..
+    (386.8980,531.3054) .. controls (390.7967,533.2802) and (394.1385,535.9385) ..
+    (396.9234,539.2802)(384.5436,593.1289) .. controls (386.5688,589.9896) and
+    (388.0625,586.3440) .. (389.0246,582.1921) .. controls (389.9866,578.0402) and
+    (390.4676,573.4072) .. (390.4677,568.2932) .. controls (390.4676,564.5464) and
+    (390.0625,560.7235) .. (389.2525,556.8247) .. controls (388.4423,552.9260) and
+    (387.1764,549.5335) .. (385.4550,546.6474) .. controls (383.7334,543.7107) and
+    (381.4802,541.3309) .. (378.6954,539.5081) .. controls (375.9105,537.6853) and
+    (372.5687,536.7739) .. (368.6700,536.7739) .. controls (364.9230,536.7739) and
+    (361.7331,537.6094) .. (359.1002,539.2802) .. controls (356.4673,540.9005) and
+    (354.1888,542.8499) .. (352.2647,545.1284) -- (352.2647,589.4073) .. controls
+    (352.7204,590.7745) and (353.4546,592.1922) .. (354.4673,593.6606) .. controls
+    (355.5305,595.1289) and (356.6951,596.3948) .. (357.9610,597.4581) .. controls
+    (359.5306,598.7239) and (361.2268,599.7619) .. (363.0496,600.5720) .. controls
+    (364.8724,601.3315) and (367.1003,601.7113) .. (369.7333,601.7113) .. controls
+    (372.5687,601.7113) and (375.3029,600.9771) .. (377.9359,599.5087) .. controls
+    (380.5688,597.9897) and (382.7713,595.8631) .. (384.5436,593.1289);
+  \path[fill=black] (452.5949,605.2809) -- (416.0629,605.2809) --
+    (416.0629,600.2682) .. controls (417.2275,600.1670) and (418.4680,600.0657) ..
+    (419.7845,599.9644) .. controls (421.1009,599.8125) and (422.1895,599.6100) ..
+    (423.0503,599.3568) .. controls (424.4680,598.9011) and (425.5313,598.1163) ..
+    (426.2402,597.0024) .. controls (426.9491,595.8378) and (427.3035,594.3441) ..
+    (427.3035,592.5213) -- (427.3035,505.7862) .. controls (427.3035,503.9635) and
+    (426.8985,502.2672) .. (426.0883,500.6975) .. controls (425.3288,499.0773) and
+    (424.3161,497.8115) .. (423.0503,496.9000) .. controls (422.1389,496.2925) and
+    (420.4680,495.7355) .. (418.0376,495.2291) .. controls (415.6072,494.7229) and
+    (413.6578,494.4191) .. (412.1894,494.3177) -- (412.1894,489.4569) --
+    (440.3670,487.7100) -- (441.4303,488.8493) -- (441.4303,591.6099) .. controls
+    (441.4302,593.3821) and (441.7593,594.8505) .. (442.4176,596.0150) .. controls
+    (443.0758,597.1290) and (444.1391,597.9897) .. (445.6075,598.5973) .. controls
+    (446.7214,599.1037) and (447.8100,599.4834) .. (448.8734,599.7366) .. controls
+    (449.9873,599.9897) and (451.2278,600.1670) .. (452.5949,600.2682) --
+    (452.5949,605.2809);
+  \path[fill=black] (493.6840,633.0028) .. controls (488.9244,633.0027) and
+    (484.5700,632.3951) .. (480.6206,631.1800) .. controls (476.6711,630.0154) and
+    (473.2787,628.4204) .. (470.4432,626.3951) .. controls (467.6078,624.3697) and
+    (465.4052,622.0406) .. (463.8356,619.4077) .. controls (462.3166,616.7747) and
+    (461.5571,614.0658) .. (461.5571,611.2810) .. controls (461.5571,608.8000) and
+    (462.1647,606.5721) .. (463.3799,604.5974) .. controls (464.5951,602.5721) and
+    (466.5445,601.5594) .. (469.2280,601.5594) .. controls (472.2660,601.5594) and
+    (474.5699,602.3189) .. (476.1395,603.8379) .. controls (477.7598,605.3063) and
+    (478.5699,607.0025) .. (478.5699,608.9266) .. controls (478.5699,610.5468) and
+    (478.2914,612.5975) .. (477.7345,615.0785) .. controls (477.2281,617.5596) and
+    (476.8230,619.3317) .. (476.5193,620.3950) .. controls (476.8737,620.8507) and
+    (477.5066,621.4583) .. (478.4180,622.2178) .. controls (479.3800,622.9773) and
+    (480.5446,623.6609) .. (481.9117,624.2685) .. controls (483.5320,625.0280) and
+    (485.2282,625.6356) .. (487.0004,626.0913) .. controls (488.7725,626.5470) and
+    (491.2789,626.7748) .. (494.5195,626.7749) .. controls (497.5574,626.7748) and
+    (500.4689,626.2685) .. (503.2537,625.2559) .. controls (506.0892,624.2432) and
+    (508.5702,622.6229) .. (510.6969,620.3950) .. controls (512.9247,618.0659) and
+    (514.6462,615.3317) .. (515.8615,612.1924) .. controls (517.1272,609.1038) and
+    (517.7602,605.0278) .. (517.7602,599.9644) .. controls (517.7602,597.2302) and
+    (517.4564,594.5213) .. (516.8488,591.8378) .. controls (516.2918,589.1542) and
+    (515.2285,586.8251) .. (513.6589,584.8503) .. controls (512.0892,582.8757) and
+    (509.9373,581.3566) .. (507.2031,580.2933) .. controls (504.5195,579.1794) and
+    (501.1018,578.6224) .. (496.9499,578.6224) -- (487.0004,578.6224) --
+    (487.0004,569.8881) -- (493.6081,569.8881) .. controls (500.5954,569.8882) and
+    (505.6335,567.9641) .. (508.7221,564.1159) .. controls (511.8107,560.2678) and
+    (513.3551,554.4703) .. (513.3551,546.7233) .. controls (513.3551,540.3942) and
+    (511.8614,535.6347) .. (508.8740,532.4447) .. controls (505.8866,529.2042) and
+    (501.6587,527.5840) .. (496.1904,527.5839) .. controls (493.5574,527.5840) and
+    (491.3801,527.9131) .. (489.6586,528.5712) .. controls (487.9877,529.1789) and
+    (486.6206,529.7865) .. (485.5573,530.3940) .. controls (484.2915,531.1030) and
+    (483.2535,531.8878) .. (482.4434,532.7485) .. controls (481.6332,533.6093) and
+    (481.0256,534.2423) .. (480.6206,534.6472) .. controls (480.9750,536.2676) and
+    (481.4054,538.2676) .. (481.9117,540.6473) .. controls (482.4180,542.9765) and
+    (482.6712,545.2044) .. (482.6712,547.3309) .. controls (482.6712,549.2044) and
+    (481.8611,550.9006) .. (480.2408,552.4196) .. controls (478.6712,553.8880) and
+    (476.3420,554.6222) .. (473.2534,554.6222) .. controls (470.5698,554.6222) and
+    (468.5951,553.6602) .. (467.3293,551.7360) .. controls (466.1141,549.8120) and
+    (465.5065,547.5842) .. (465.5065,545.0524) .. controls (465.5065,542.4195) and
+    (466.2407,539.7360) .. (467.7090,537.0017) .. controls (469.1774,534.2676) and
+    (471.3546,531.7106) .. (474.2408,529.3307) .. controls (477.1268,526.9510) and
+    (480.6459,525.0270) .. (484.7978,523.5585) .. controls (488.9497,522.0902) and
+    (493.7346,521.3560) .. (499.1524,521.3560) .. controls (505.3803,521.3560) and
+    (510.5196,522.2928) .. (514.5703,524.1661) .. controls (518.6716,525.9890) and
+    (521.8868,528.2169) .. (524.2160,530.8497) .. controls (526.4944,533.4321) and
+    (528.0641,536.1410) .. (528.9249,538.9764) .. controls (529.7856,541.8119) and
+    (530.2160,544.2424) .. (530.2161,546.2676) .. controls (530.2160,548.7994) and
+    (529.8615,551.3563) .. (529.1527,553.9386) .. controls (528.4438,556.4703) and
+    (527.2792,558.8248) .. (525.6590,561.0020) .. controls (523.8868,563.3818) and
+    (521.5323,565.5590) .. (518.5957,567.5337) .. controls (515.7095,569.4578) and
+    (512.0639,571.0274) .. (507.6588,572.2426) -- (507.6588,573.4578) .. controls
+    (510.4943,573.7110) and (513.5070,574.3439) .. (516.6969,575.3566) .. controls
+    (519.9374,576.3693) and (522.8488,577.8629) .. (525.4312,579.8376) .. controls
+    (528.1147,581.9136) and (530.3172,584.5972) .. (532.0389,587.8883) .. controls
+    (533.7603,591.1289) and (534.6211,595.2555) .. (534.6212,600.2682) .. controls
+    (534.6211,609.9898) and (530.7223,617.8633) .. (522.9248,623.8887) .. controls
+    (515.1272,629.9647) and (505.3803,633.0027) .. (493.6840,633.0028);
+  \path[fill=maincolor] (239.7096,586.3724) .. controls (236.5703,592.3472) and
+    (232.3677,597.1067) .. (227.1019,600.6510) .. controls (221.8359,604.1954) and
+    (215.7852,605.9676) .. (208.9498,605.9676) .. controls (202.9244,605.9676) and
+    (197.6332,604.9043) .. (193.0762,602.7777) .. controls (188.5698,600.6510) and
+    (184.8482,597.7649) .. (181.9115,594.1193) .. controls (178.9748,590.4737) and
+    (176.7722,586.2205) .. (175.3038,581.3597) .. controls (173.8861,576.4989) and
+    (173.1772,571.3596) .. (173.1772,565.9418) .. controls (173.1772,561.0810) and
+    (173.9367,556.3215) .. (175.4557,551.6632) .. controls (177.0254,546.9543) and
+    (179.3039,542.7264) .. (182.2913,538.9795) .. controls (185.1773,535.3846) and
+    (188.7470,532.4985) .. (193.0002,530.3212) .. controls (197.3040,528.0934) and
+    (202.1142,526.9794) .. (207.4308,526.9794) .. controls (212.8991,526.9794) and
+    (217.5827,527.8402) .. (221.4816,529.5617) .. controls (225.3803,531.2833) and
+    (228.5449,533.6377) .. (230.9753,536.6250) .. controls (233.3044,539.4606) and
+    (235.0259,542.8024) .. (236.1399,546.6505) .. controls (237.3045,550.4987) and
+    (237.8867,554.6759) .. (237.8868,559.1822) -- (237.8868,564.1950) --
+    (188.2913,564.1950) .. controls (188.2913,569.1064) and (188.7470,573.5622) ..
+    (189.6584,577.5622) .. controls (190.6204,581.5623) and (192.1141,585.0813) ..
+    (194.1395,588.1193) .. controls (196.1142,591.0560) and (198.6965,593.3852) ..
+    (201.8864,595.1067) .. controls (205.0763,596.7776) and (208.8738,597.6131) ..
+    (213.2789,597.6130) .. controls (217.7853,597.6131) and (221.6587,596.5751) ..
+    (224.8993,594.4991) .. controls (228.1904,592.3725) and (231.3550,588.5750) ..
+    (234.3931,583.1066) -- (239.7096,586.3724)(222.9246,557.8151) .. controls
+    (222.9246,554.9797) and (222.6714,551.9417) .. (222.1651,548.7011) .. controls
+    (221.7094,545.4606) and (220.9499,542.7517) .. (219.8866,540.5744) .. controls
+    (218.7220,538.2454) and (217.1270,536.3466) .. (215.1017,534.8782) .. controls
+    (213.0764,533.4099) and (210.4687,532.6757) .. (207.2789,532.6756) .. controls
+    (201.9623,532.6757) and (197.5319,534.9036) .. (193.9876,539.3592) .. controls
+    (190.4939,543.7644) and (188.5951,549.9164) .. (188.2913,557.8151) --
+    (222.9246,557.8151);
+  \path[fill=maincolor] (320.6725,603.9929) -- (286.3430,603.9929) --
+    (286.3430,598.9801) .. controls (288.6215,598.7270) and (290.5456,598.4738) ..
+    (292.1152,598.2206) .. controls (293.7355,597.9675) and (294.5456,597.3093) ..
+    (294.5457,596.2459) .. controls (294.5456,595.7902) and (294.2924,595.0814) ..
+    (293.7862,594.1193) .. controls (293.2798,593.1573) and (292.7734,592.2712) ..
+    (292.2672,591.4611) .. controls (291.0013,589.4864) and (289.2544,586.8535) ..
+    (287.0266,583.5623) .. controls (284.8493,580.2205) and (282.1657,576.2457) ..
+    (278.9759,571.6381) .. controls (276.3429,574.9293) and (273.9125,578.1445) ..
+    (271.6846,581.2838) .. controls (269.4567,584.3724) and (267.1276,587.6636) ..
+    (264.6972,591.1573) .. controls (264.3428,591.6636) and (263.9630,592.2965) ..
+    (263.5580,593.0560) .. controls (263.2035,593.8155) and (263.0263,594.4231) ..
+    (263.0263,594.8788) .. controls (263.0263,595.9928) and (263.7352,596.9295) ..
+    (265.1529,597.6890) .. controls (266.6213,598.3979) and (268.7985,598.8789) ..
+    (271.6846,599.1321) -- (271.6846,603.9929) -- (243.9628,603.9929) --
+    (243.9628,599.2840) .. controls (247.4059,598.2713) and (250.1654,597.0561) ..
+    (252.2414,595.6383) .. controls (254.3680,594.1700) and (256.3174,592.3725) ..
+    (258.0896,590.2459) .. controls (259.6592,588.2206) and (261.8364,585.4357) ..
+    (264.6213,581.8914) .. controls (267.4567,578.3470) and (271.1023,573.5369) ..
+    (275.5581,567.4608) .. controls (272.9758,563.7646) and (269.8112,559.2582) ..
+    (266.0643,553.9417) .. controls (262.3681,548.5746) and (259.3047,544.1188) ..
+    (256.8744,540.5744) .. controls (255.5579,538.6504) and (254.0389,537.1061) ..
+    (252.3173,535.9415) .. controls (250.6464,534.7263) and (248.2667,534.1187) ..
+    (245.1780,534.1187) -- (245.1780,529.1060) -- (277.7607,529.1060) --
+    (277.7607,534.1187) .. controls (276.1404,534.1187) and (274.5454,534.2200) ..
+    (272.9758,534.4225) .. controls (271.4061,534.6251) and (270.6213,535.0808) ..
+    (270.6213,535.7896) .. controls (270.6213,536.2453) and (270.7732,536.7517) ..
+    (271.0770,537.3086) .. controls (271.3808,537.8656) and (271.7606,538.4732) ..
+    (272.2163,539.1314) .. controls (273.3302,540.8530) and (275.0517,543.5112) ..
+    (277.3809,547.1062) .. controls (279.7606,550.7012) and (282.3176,554.4987) ..
+    (285.0519,558.4987) .. controls (286.8240,556.0683) and (288.8747,553.2329) ..
+    (291.2038,549.9923) .. controls (293.5836,546.7518) and (295.7608,543.6631) ..
+    (297.7356,540.7263) .. controls (297.9380,540.3720) and (298.1406,539.9416) ..
+    (298.3432,539.4352) .. controls (298.5456,538.8783) and (298.6469,538.3466) ..
+    (298.6470,537.8402) .. controls (298.6469,536.7770) and (297.7608,535.9415) ..
+    (295.9887,535.3339) .. controls (294.2671,534.6757) and (292.6215,534.2200) ..
+    (291.0519,533.9668) -- (291.0519,529.1060) -- (318.6978,529.1060) --
+    (318.6978,533.8149) .. controls (314.7990,534.8276) and (311.7610,536.0428) ..
+    (309.5838,537.4605) .. controls (307.4065,538.8277) and (305.5584,540.4226) ..
+    (304.0394,542.2453) .. controls (302.3685,544.3214) and (300.3684,546.8784) ..
+    (298.0394,549.9163) .. controls (295.7608,552.9544) and (292.5456,557.2076) ..
+    (288.3937,562.6760) .. controls (293.0013,569.1571) and (296.7482,574.4736) ..
+    (299.6343,578.6255) .. controls (302.5204,582.7775) and (305.4318,587.0560) ..
+    (308.3686,591.4611) .. controls (309.8369,593.6890) and (311.4572,595.4611) ..
+    (313.2294,596.7776) .. controls (315.0521,598.0434) and (317.5332,598.7776) ..
+    (320.6725,598.9801) -- (320.6725,603.9929);
+  \path[fill=maincolor] (395.6354,537.9921) .. controls (398.6227,541.5365) and
+    (400.9265,545.6632) .. (402.5468,550.3720) .. controls (404.2177,555.0303) and
+    (405.0531,560.3722) .. (405.0532,566.3975) .. controls (405.0531,572.3216) and
+    (404.0658,577.7394) .. (402.0911,582.6508) .. controls (400.1164,587.5117) and
+    (397.5087,591.6636) .. (394.2683,595.1067) .. controls (390.8758,598.6004) and
+    (387.1036,601.2840) .. (382.9517,603.1574) .. controls (378.7997,605.0308) and
+    (374.3946,605.9676) .. (369.7363,605.9676) .. controls (365.2299,605.9676) and
+    (361.5337,605.4612) .. (358.6476,604.4486) .. controls (355.7615,603.4359) and
+    (353.4070,602.2460) .. (351.5843,600.8789) -- (350.9766,600.8789) --
+    (350.9766,623.3602) .. controls (350.9766,625.1829) and (351.3311,626.7019) ..
+    (352.0400,627.9172) .. controls (352.7488,629.1323) and (353.8374,630.0184) ..
+    (355.3058,630.5754) .. controls (356.5210,631.0311) and (358.2425,631.4615) ..
+    (360.4704,631.8666) .. controls (362.7489,632.3223) and (364.6223,632.5754) ..
+    (366.0907,632.6261) -- (366.0907,637.7147) -- (324.2422,637.7147) --
+    (324.2422,632.6261) .. controls (325.8118,632.5248) and (327.3308,632.3982) ..
+    (328.7992,632.2463) .. controls (330.2676,632.0944) and (331.5840,631.8412) ..
+    (332.7486,631.4868) .. controls (334.2676,630.9805) and (335.3309,630.0944) ..
+    (335.9385,628.8286) .. controls (336.5461,627.5627) and (336.8499,626.0690) ..
+    (336.8499,624.3475) -- (336.8499,544.6758) .. controls (336.8499,543.1568) and
+    (336.4701,541.6884) .. (335.7107,540.2706) .. controls (334.9511,538.8530) and
+    (333.9638,537.7137) .. (332.7486,536.8529) .. controls (331.8372,536.2453) and
+    (330.5714,535.7896) .. (328.9511,535.4858) .. controls (327.3308,535.1314) and
+    (325.7612,534.9036) .. (324.2422,534.8022) -- (324.2422,529.8655) --
+    (349.7614,528.1945) -- (350.8247,529.1060) -- (350.8247,537.5364) --
+    (351.4323,537.6883) .. controls (354.0653,534.6504) and (357.3311,532.1187) ..
+    (361.2299,530.0933) .. controls (365.1287,528.0680) and (369.0021,527.0554) ..
+    (372.8503,527.0553) .. controls (377.5085,527.0554) and (381.7617,528.0427) ..
+    (385.6099,530.0174) .. controls (389.5087,531.9921) and (392.8505,534.6504) ..
+    (395.6354,537.9921)(383.2555,591.8408) .. controls (385.2808,588.7016) and
+    (386.7744,585.0560) .. (387.7365,580.9040) .. controls (388.6985,576.7521) and
+    (389.1795,572.1191) .. (389.1796,567.0051) .. controls (389.1795,563.2583) and
+    (388.7745,559.4354) .. (387.9644,555.5366) .. controls (387.1542,551.6379) and
+    (385.8884,548.2455) .. (384.1669,545.3593) .. controls (382.4453,542.4226) and
+    (380.1921,540.0428) .. (377.4073,538.2200) .. controls (374.6224,536.3972) and
+    (371.2806,535.4858) .. (367.3819,535.4858) .. controls (363.6350,535.4858) and
+    (360.4451,536.3213) .. (357.8122,537.9921) .. controls (355.1792,539.6125) and
+    (352.9007,541.5618) .. (350.9766,543.8403) -- (350.9766,588.1193) .. controls
+    (351.4323,589.4864) and (352.1665,590.9041) .. (353.1792,592.3725) .. controls
+    (354.2425,593.8409) and (355.4070,595.1067) .. (356.6729,596.1700) .. controls
+    (358.2425,597.4358) and (359.9387,598.4738) .. (361.7616,599.2839) .. controls
+    (363.5843,600.0434) and (365.8122,600.4232) .. (368.4452,600.4232) .. controls
+    (371.2806,600.4232) and (374.0148,599.6890) .. (376.6478,598.2206) .. controls
+    (379.2807,596.7016) and (381.4833,594.5750) .. (383.2555,591.8408);
+  \path[fill=basecolor] (451.3069,603.9929) -- (414.7748,603.9929) --
+    (414.7748,598.9801) .. controls (415.9394,598.8789) and (417.1799,598.7776) ..
+    (418.4964,598.6763) .. controls (419.8128,598.5245) and (420.9015,598.3219) ..
+    (421.7622,598.0687) .. controls (423.1800,597.6130) and (424.2433,596.8282) ..
+    (424.9521,595.7143) .. controls (425.6610,594.5497) and (426.0154,593.0560) ..
+    (426.0155,591.2332) -- (426.0155,504.4981) .. controls (426.0154,502.6754) and
+    (425.6104,500.9792) .. (424.8002,499.4094) .. controls (424.0407,497.7893) and
+    (423.0281,496.5234) .. (421.7622,495.6119) .. controls (420.8508,495.0044) and
+    (419.1799,494.4475) .. (416.7495,493.9410) .. controls (414.3191,493.4348) and
+    (412.3697,493.1310) .. (410.9014,493.0296) -- (410.9014,488.1688) --
+    (439.0789,486.4219) -- (440.1422,487.5612) -- (440.1422,590.3218) .. controls
+    (440.1422,592.0940) and (440.4713,593.5624) .. (441.1295,594.7269) .. controls
+    (441.7877,595.8409) and (442.8510,596.7016) .. (444.3195,597.3092) .. controls
+    (445.4334,597.8156) and (446.5220,598.1953) .. (447.5853,598.4485) .. controls
+    (448.6992,598.7017) and (449.9397,598.8789) .. (451.3069,598.9801) --
+    (451.3069,603.9929);
+  \path[fill=basecolor] (492.3959,631.7147) .. controls (487.6364,631.7147) and
+    (483.2819,631.1071) .. (479.3325,629.8919) .. controls (475.3831,628.7273) and
+    (471.9906,627.1323) .. (469.1552,625.1070) .. controls (466.3197,623.0817) and
+    (464.1171,620.7525) .. (462.5475,618.1196) .. controls (461.0285,615.4866) and
+    (460.2690,612.7778) .. (460.2690,609.9929) .. controls (460.2690,607.5119) and
+    (460.8766,605.2840) .. (462.0918,603.3093) .. controls (463.3070,601.2840) and
+    (465.2564,600.2713) .. (467.9400,600.2713) .. controls (470.9780,600.2713) and
+    (473.2818,601.0308) .. (474.8514,602.5498) .. controls (476.4717,604.0182) and
+    (477.2818,605.7144) .. (477.2819,607.6385) .. controls (477.2818,609.2587) and
+    (477.0033,611.3094) .. (476.4464,613.7904) .. controls (475.9400,616.2715) and
+    (475.5350,618.0436) .. (475.2312,619.1069) .. controls (475.5856,619.5626) and
+    (476.2185,620.1702) .. (477.1300,620.9298) .. controls (478.0920,621.6892) and
+    (479.2565,622.3728) .. (480.6237,622.9804) .. controls (482.2439,623.7399) and
+    (483.9401,624.3475) .. (485.7123,624.8032) .. controls (487.4845,625.2589) and
+    (489.9908,625.4868) .. (493.2314,625.4868) .. controls (496.2694,625.4868) and
+    (499.1808,624.9804) .. (501.9657,623.9678) .. controls (504.8011,622.9551) and
+    (507.2821,621.3348) .. (509.4088,619.1069) .. controls (511.6366,616.7778) and
+    (513.3581,614.0436) .. (514.5734,610.9043) .. controls (515.8392,607.8157) and
+    (516.4721,603.7397) .. (516.4721,598.6763) .. controls (516.4721,595.9421) and
+    (516.1683,593.2333) .. (515.5607,590.5497) .. controls (515.0037,587.8661) and
+    (513.9404,585.5370) .. (512.3708,583.5622) .. controls (510.8011,581.5876) and
+    (508.6492,580.0686) .. (505.9151,579.0052) .. controls (503.2314,577.8913) and
+    (499.8137,577.3344) .. (495.6618,577.3343) -- (485.7123,577.3343) --
+    (485.7123,568.6001) -- (492.3200,568.6001) .. controls (499.3074,568.6001) and
+    (504.3454,566.6760) .. (507.4341,562.8279) .. controls (510.5227,558.9797) and
+    (512.0670,553.1822) .. (512.0670,545.4352) .. controls (512.0670,539.1061) and
+    (510.5733,534.3466) .. (507.5860,531.1566) .. controls (504.5985,527.9162) and
+    (500.3707,526.2959) .. (494.9023,526.2958) .. controls (492.2693,526.2959) and
+    (490.0921,526.6250) .. (488.3706,527.2831) .. controls (486.6996,527.8908) and
+    (485.3325,528.4984) .. (484.2693,529.1060) .. controls (483.0034,529.8149) and
+    (481.9654,530.5997) .. (481.1553,531.4604) .. controls (480.3451,532.3213) and
+    (479.7375,532.9542) .. (479.3325,533.3592) .. controls (479.6869,534.9795) and
+    (480.1173,536.9795) .. (480.6237,539.3592) .. controls (481.1300,541.6884) and
+    (481.3831,543.9163) .. (481.3832,546.0429) .. controls (481.3831,547.9164) and
+    (480.5730,549.6126) .. (478.9527,551.1315) .. controls (477.3831,552.5999) and
+    (475.0539,553.3341) .. (471.9653,553.3341) .. controls (469.2817,553.3341) and
+    (467.3070,552.3721) .. (466.0412,550.4480) .. controls (464.8260,548.5240) and
+    (464.2184,546.2961) .. (464.2184,543.7643) .. controls (464.2184,541.1315) and
+    (464.9526,538.4479) .. (466.4210,535.7136) .. controls (467.8893,532.9795) and
+    (470.0666,530.4225) .. (472.9527,528.0426) .. controls (475.8388,525.6630) and
+    (479.3578,523.7389) .. (483.5098,522.2704) .. controls (487.6617,520.8021) and
+    (492.4465,520.0680) .. (497.8643,520.0679) .. controls (504.0922,520.0680) and
+    (509.2315,521.0047) .. (513.2822,522.8780) .. controls (517.3835,524.7009) and
+    (520.5987,526.9288) .. (522.9279,529.5617) .. controls (525.2064,532.1440) and
+    (526.7760,534.8529) .. (527.6368,537.6883) .. controls (528.4975,540.5239) and
+    (528.9279,542.9543) .. (528.9280,544.9795) .. controls (528.9279,547.5113) and
+    (528.5735,550.0683) .. (527.8647,552.6505) .. controls (527.1557,555.1822) and
+    (525.9912,557.5367) .. (524.3710,559.7139) .. controls (522.5987,562.0937) and
+    (520.2443,564.2709) .. (517.3076,566.2456) .. controls (514.4214,568.1697) and
+    (510.7758,569.7393) .. (506.3708,570.9545) -- (506.3708,572.1697) .. controls
+    (509.2062,572.4229) and (512.2189,573.0558) .. (515.4088,574.0685) .. controls
+    (518.6493,575.0812) and (521.5607,576.5749) .. (524.1431,578.5495) .. controls
+    (526.8266,580.6255) and (529.0292,583.3091) .. (530.7508,586.6003) .. controls
+    (532.4722,589.8408) and (533.3330,593.9674) .. (533.3331,598.9801) .. controls
+    (533.3330,608.7018) and (529.4342,616.5753) .. (521.6368,622.6007) .. controls
+    (513.8391,628.6766) and (504.0922,631.7147) .. (492.3959,631.7147);
+\end{tikzpicture}
+}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\publicationmonth{March}
+\publicationyear{2014}
+\publicationissue{9}
+
+\usepackage{multicol}
+\usepackage{xparse}
+\newcommand\ctanpkg[1]{\href{http://ctan.org/pkg/#1}{\pkg{#1}}}
+
+\begin{document}
+\maketitle
+
+\raisefirstsection
+
+\tableofcontents     % could drop this and raise first section instead
+
+\section{Hiatus?}
+
+Well, it's been a busy couple of years.
+Work has slowed on the \LaTeX3 codebase as all active members of the team have been\Dash shall we say\Dash busily occupied with more pressing concerns in their day-to-day activities.
+
+Nonetheless, Joseph and Bruno have continued to fine-tune the \LaTeX3 kernel and add-on packages.
+Browsing through the commit history shows bug fixes and improvements to documentation, test files, and internal code across the entire breadth of the codebase.
+
+Members of the team have presented at two TUG conferences since the last \LaTeX3 news. (Has it really been so long?)
+In July 2012, Frank and Will travelled to Boston; Frank discussed the challenges faced in the past and continuing to the present day due to the limits of the various \TeX\ engines; and, Frank and Will together covered a brief history and recent developments of the \pkg{expl3} code.
+
+In 2013, Joseph and Frank wrote a talk on complex layouts, and the "layers" ideas discussed in \LaTeX3; Frank went to Tokyo in October to present the work.
+Slides of and recordings from these talks are available on the \LaTeX3 website.
+
+These conferences are good opportunities to introduce the \pkg{expl3} language to a wider group of people; in many cases, explaining the rationale behind why \pkg{expl3} looks a little strange at first helps to convince the audience that it's not so weird after all.
+In our experience, anyone that's been exposed to some of the more awkward expansion aspects of \TeX\ programming appreciates how \pkg{expl3} makes life much easier for us.
+
+\section{\pkg{expl3} in the community}
+
+While things have been slightly quieter for the team, more and more people are adopting \pkg{expl3} for their own use.
+A search on the \TeX\ Stack Exchange website for either "\texttt{expl3}" or "\texttt{latex3}" at time of writing yield around one thousand results each.
+
+In order to help standardise the prefixes used in \pkg{expl3} modules, we have developed a registration procedure for package authors (which amounts to little more than notifying us that their package uses a specific prefix, which will often be the name of the package itself).
+Please contact us via the \texttt{latex-l} mailing list to register your module prefixes and package names; we ask that you avoid using package names that begin with \texttt{l3...}\ since \pkg{expl3} packages use this internally.
+Some authors have started using the package prefix \texttt{lt3...}\ as a way of indicating their package builds on \pkg{expl3} in some way but is not maintained by the \LaTeX3 team.
+
+In the prefix database at present, some thirty package prefixes are registered by fifteen separate individuals (unrelated to The \LaTeX{} Project\Dash the number of course grows if you include packages by members of the team).
+These packages cover a broad range of functionality:
+\begin{description}
+\item[\ctanpkg{acro}] Interface for creating (classes of) acronyms
+\item[\ctanpkg{hobby}]
+Hobby's algorithm in PGF/TiKZ for drawing optimally smooth curves.
+\item[\ctanpkg{chemmacros}] Typesetting in the field of chemistry.
+\item[\ctanpkg{classics}] Traditional-style citations for the classics.
+\item[\ctanpkg{conteq}] Continued (in)equalities in mathematics.
+\item[\ctanpkg{ctex}] A collection of macro packages and document classes for Chinese typesetting.
+\item[\ctanpkg{endiagram}] Draw potential energy curve diagrams.
+\item[\ctanpkg{enotez}] Support for end-notes.
+\item[\ctanpkg{exsheets}] Question sheets and exams with  metadata.
+%(Note to self: remember to use this for teaching this semester!)
+\item[\ctanpkg{lt3graph}] A graph data structure.
+\item[\ctanpkg{newlfm}] The venerable class for memos and letters.
+\item[\ctanpkg{fnpct}] Interaction between footnotes and punctuation.
+\item[\ctanpkg{GS1}] Barcodes and so forth.
+\item[\ctanpkg{hobete}] Beamer theme for the Univ.\ of Hohenheim.
+\item[\ctanpkg{kantlipsum}] Generate sentences in Kant's style.
+\item[\ctanpkg{lualatex-math}] Extended support for mathematics in \LuaLaTeX.
+\item[\ctanpkg{media9}] Multimedia inclusion for Adobe Reader.
+\item[\ctanpkg{pkgloader}] Managing the options and loading order of other packages.
+\item[\ctanpkg{substances}] Lists of chemicals, etc., in a document.
+\item[\ctanpkg{withargs}] Ephemeral macro use.
+\item[\ctanpkg{xecjk}] Support for CJK documents in \XeLaTeX.
+\item[\ctanpkg{xpatch}, \ctanpkg{regexpatch}] Patch command definitions.
+\item[\ctanpkg{xpeek}]  Commands that peek ahead in the input stream.
+\item[\ctanpkg{xpinjin}] Automatically add pinyin to Chinese characters
+\item[\ctanpkg{zhnumber}] Typeset Chinese representations of numbers
+\item[\ctanpkg{zxjatype}] Standards-conforming typesetting of Japanese for \XeLaTeX.
+\end{description}
+Some of these packages are marked by their authors as experimental, but it is clear that these packages have been developed to solve specific needs for typesetting and document production.
+
+The \pkg{expl3} language has well and truly gained traction after many years of waiting patiently.
+
+\section[Logo for the \LaTeX3 Programming Language]
+            {A logo for the \LaTeX3 Programming Language}
+
+To show that \pkg{expl3} is ready for general use Paulo Cereda drew up a nice logo for us, showing a \mbox{hummingbird} (agile and fast\Dash but needs huge amounts of energy) picking at "l3". Big thanks to Paulo!
+\begin{center}
+\explogo
+\end{center}
+
+\section{Recent activity}
+
+\LaTeX3 work has only slowed, not ground to a halt.
+While changes have tended to be minor in recent times, there are a number of improvements worth discussing explicitly.
+\begin{enumerate}
+\item
+Bruno has extended the floating point code to cover additional functions such as inverse trigonometric functions.
+These additions round out the functionality well and make it viable for use in most cases needing floating point mathematics.
+\item
+Joseph's refinement of the experimental galley code now allows separation of paragraph shapes from margins/cutouts.
+This still needs some testing!
+\item
+For some time now \pkg{expl3} has provided "native" drivers although they have not been selected by default in most cases.
+These have been revised to improve robustness, which makes them probably ready to enable by default.
+The improvements made to the drivers have also fed back to more "general" \LaTeX\ code.
+\end{enumerate}
+
+
+\section{Work in progress}
+
+We're still actively discussing a variety of areas to tackle next.
+We are aware of various "odds and ends" in \pkg{expl3} that still need sorting out.
+In particular, some experimental functions have been working quite well and it's time to assess moving them into the "stable" modules, in particular the \pkg{l3str} module for dealing with catcode-twelve token lists more commonly known in \pkg{expl3} as \emph{strings}.
+
+Areas of active discussion including issues around uppercasing and lowercasing (and the esoteric ways that this can be achieved in \TeX) and space skipping (or not) in commands and environments with optional arguments.
+These two issues are discussed next.
+
+\subsection{Uppercasing and lowercasing}
+
+The commands \verb"\tl_to_lowercase:n" and \verb"\tl_to_uppercase:n" have long been overdue for a good hard look.
+From a traditional \TeX\ viewpoint, these commands are simply the primitive \verb"\lowercase" and \verb"\uppercase", and in practice it's well known that there are various limitations and peculiarities associated with them.
+We know these commands are good, to one extent or another, for three things:
+\begin{enumerate}
+\item
+Uppercasing text for typesetting purposes such as all-uppercase titles.
+\item
+Lowercasing text for normalisation in sorting and other applications such as filename comparisons.
+\item
+Achieving special effects, in concert with manipulating \verb"\uccode" and the like, such as defining commands that contain characters with different catcodes than usual.
+\end{enumerate}
+We are working on providing a set of commands to achieve all three of these functions in a more direct and easy-to-use fashion, including support for Unicode in \LuaLaTeX\ and \XeLaTeX.
+
+\pagebreak
+
+\subsection{Space-skipping in \pkg{xparse}}
+
+We have also re-considered the behaviour of space-skipping in \pkg{xparse}.
+Consider the following examples:
+\begin{verbatim}
+\begin{dmath}        \begin{dmath}[label=foo]
+[x y z] = [1 2 3]    x^2 + y^2 = z^2
+\end{dmath}          \end{dmath}
+\end{verbatim}
+In the first case, we are typesetting some mathematics that contains square brackets.
+In the second, we are assigning a label to the equation using an optional argument, which also uses  brackets.
+The fact that both work correctly is due to behaviour that is specifically programmed into the workings of the \texttt{dmath} environment of \pkg{breqn}: spaces before an optional argument are explicitly forbidden.
+At present, this is also how commands and environments defined using \pkg{xparse} behave.
+But consider a \pkg{pgfplots} environment:
+\begin{verbatim}
+\begin{pgfplot}
+  [
+    % plot options
+  ]
+  \begin{axis}
+    [
+      % axis options
+    ]
+    ...
+  \end{axis}
+\end{pgfplot}
+\end{verbatim}
+This would seem like quite a natural way to write such environments, but with the current state of \pkg{xparse} this syntax would be incorrect. One would have to write either of these instead:
+\begin{multicols}{2}
+\begin{verbatim}
+\begin{pgfplot}%
+  [
+   % plot options
+  ]
+\end{verbatim}
+\begin{verbatim}
+\begin{pgfplot}[
+   % plot options
+  ]
+\end{verbatim}
+\end{multicols}
+Is this an acceptable compromise?
+We're not entirely sure here\Dash we're in a corner because the humble \texttt{[} has ended up being part of both the syntax and semantics of a \LaTeX\ document.
+
+%There is one further matter to consider and that is how "control symbols" such as \verb"\\" behave in such matters.
+%Because \TeX\ does not skip spaces after control symbols, neither does \pkg{xparse}; therefore control symbols are a solution if one desires a command to use in a mathematics context where an optional argument could cause issues.
+%An example for this from \pkg{amsmath} is line breaks in multi-line display equations:
+%\begin{verbatim}
+%\begin{align}
+%a &= b+c \\
+%[x y z] &= [1 2 3]
+%\end{align}
+%\end{verbatim}
+%In \pkg{amsmath} this requires specific measures to be taken to allow \verb"\\" to behave correctly; with \pkg{xparse} this functionality is built in.
+
+Despite the current design covering most regular use-cases, we have considered adding a further option to \pkg{xparse} to define the space-skipping behaviour as desired by a package author.
+But at this very moment we've rejected adding this additional complexity, because environments that change their parsing behaviour based on their intended use make a \LaTeX-based language more difficult to predict; one could imagine such behaviour causing difficulties down the road for automatic syntax checkers and so forth.
+However, we don't make such decisions in a vacuum and we're always happy to continue to discuss such matters.
+
+
+\section{\ldots and for 2014 onwards}
+
+There is one (understandable) misconception that shows up once in a while with people claiming that
+\[
+         \textrm{\pkg{expl3}} = \textrm{\LaTeX3}.
+\]
+However, the correct relation would be a subset,
+\[
+         \textrm{\pkg{expl3}} \subset \textrm{\LaTeX3},
+\]
+with \pkg{expl3} forming the Core Language Layer on which  there will eventually be several other layers on top that \mbox{provide}
+\begin{itemize}
+\item higher-level concepts for typesetting (Typesetting Foundation Layer),
+\item a designer interface for specifying document structures and layouts (Designer Layer),
+\item and finally a Document Representation Layer that implements document level syntax.
+\end{itemize}
+Of those four layers, the lowest one\Dash\pkg{expl3}\Dash is available for use and with \pkg{xparse} we have an instance of the Document Representation Layer modeled largely after \LaTeXe{} syntax (there could be others). Both can be successfully used within the current \LaTeXe{} framework and as mentioned above this is increasingly happening.
+
+The middle layers, however, where the rubber meets the road, are still  at the level of prototypes and ideas (templates, \pkg{ldb}, galley, \pkg{xor} and all the good stuff) that need to be revised and further developed to arrive at a \LaTeX3 environment that can stand on its own and that is to where we want to return in 2014.
+
+An overview on this can be found in the answer to "What can *I* do to help The \LaTeX{} Project?"\ on Stack Exchange,\footnote{\url{http://tex.stackexchange.com/questions/45838}}
+which is reproduced below in slightly abridged form.
+This is of course not the first time that we have discussed such matters, and you can find similar material in other publications such as those at \url{http://latex-project.org}; e.g., the architecture talk given at the TUG 2011 conference.
+
+\bigskip
+
+\begin{center}
+\explbanner
+\end{center}
+
+\newpage
+\section{What can you do for The \LaTeX{} Project?}
+\textbf{By Frank Mittelbach}
+
+My vision of \LaTeX3 is really a system with multiple layers that provide interfaces for different kinds of roles. These layers are
+\begin{itemize}
+\item the underlying engine (some \TeX\ variant)
+\item the programming layer (the core language, i.e., \pkg{expl3})
+\item the typesetting foundation layer (providing higher-level concepts for typesetting)
+\item the typesetting element layer (templates for all types of document elements)
+\item the designer interface foundation layer
+\item the class designer layer (where instances of document elements with specific settings are defined)
+\item document representation layer (that provides the input syntax, i.e., how the author uses elements)
+\end{itemize}
+If you look at it from the perspective of user roles then there are at least three or four roles that you can clearly distinguish:
+\begin{itemize}
+\item The Programmer (template and functionality provider)
+\item The Document Type Designer (defines which elements are available; abstract syntax and semantics)
+\item The Designer (typography and layout)
+\item The Author (content)
+\end{itemize}
+As a consequence The \LaTeX{} Project needs different kinds of help depending on what layer or role we are looking at.
+
+The "Author" is using, say, list structures by specifying something like \verb"\begin{itemize} \item" in his documents. Or perhaps by writing \Verb|<ul> ... </ul>| or whatever the UI representation offers to him.
+
+The "Document Type Designer" defines what kind of abstract document elements are available, and what attributes or arguments those elements provide at the author level. E.g., he may specify that a certain class of documents provides the display lists "enumerate", "itemize" and "description".
+
+The "Programmer" on the other hand implements templates (that offer customizations) for such document elements, e.g., for display lists. What kind of customization possibilities should be provided by the "Programmer" is the domain of the "Document Designer"; he drives what kind of flexibility he needs for the design. In most cases the "Document Designer" should be able to simply select templates (already written) from a template library and only focus on the design, i.e., instantiating the templates with values so that the desired layout for "itemize" lists, etc., is created.
+
+In real life a single person may end up playing more than one role, but it is important to recognise that all of them come with different requirements with respect to interfaces and functionality.
+
+\subsection{Programming Layer}
+
+The programming layer consists of a core language layer (called \pkg{expl3} (EXP erimental L aTeX 3) for historical reasons and now we are stuck with it \texttt{:-)}) and two more components: the "Typesetting Foundation Layer" that we are currently working on and the "Typesetting Element Layer" that is going to provide customizable objects for the design layer. While \pkg{expl3} is in many parts already fairly complete and usable the other two are under construction.
+
+Help is needed for the programming layer in
+\begin{itemize}
+\item helping by extending and completing the regression test suite for \pkg{expl3}
+\item helping with providing good or better documentation, including tutorials
+\item possibly helping in coding additional core functionality\Dash but that requires, in contrast to the first two points, a good amount of commitment and experience with the core language as otherwise the danger is too high that the final results will end up being inconsistent
+\end{itemize}
+Once we are a bit further along with the "Typesetting Foundation Layer" we would need help in
+providing higher-level functionality, perhaps rewriting existing packages/code for elements making use of extended possibilities.
+Two steps down the road (once the "\mbox{Designer} Layer" is closer to being finalized) we would need help with developing templates for all kinds of elements.
+
+In summary for this part, we need help from people interested in programming in \TeX\ and \pkg{expl3} and/or interested in providing documentation (but for this a thorough understanding of the programming concepts is necessary too).
+
+\subsection{Design Layer}
+
+The intention of the design layer is to provide interfaces that allow specifying layout and typography styles in a declarative way. On the implementation side there are a number of prototypes (most notably \pkg{xtemplate} and the recent reimplementation of \pkg{ldb}).
+These need to be unified into a common model which requires some more experimentation and probably also some further thoughts.
+
+But the real importance of this layer is not the implementation of its interfaces but the conceptual view of it: provisioning a rich declarative method (or methods) to describe design and layout. I.e., enabling a designer to think not in programs but in visual representations and relationships.
+
+So here is the big area where people who do not feel they can or want to program \TeX's bowels can help. What would be extremely helpful (and in fact not just for \LaTeX3) would be
+\begin{itemize}
+\item collecting and classifying a \emph{huge} set of layouts and designs
+\begin{itemize}[nosep]
+\item designs for individual document elements (such as headings, TOCs, etc)
+\item document designs that include relationships between document elements
+\end{itemize}
+\item thinking about good, declarative ways to specify such designs
+\begin{itemize}[nosep]
+\item what needs to be specified
+\item to what extent and with what flexibility
+\end{itemize}
+\end{itemize}
+I believe that this is a huge task (but rewarding in itself) and already the first part of collecting existing design specifications will be a major undertaking and will need coordination and probably a lot of work. But it will be a huge asset towards testing any implementations and interfaces for this layer later on.
+
+\subsection{Document Interface Layer}
+
+If we get the separation done correctly, then this layer should effectively offer nothing more than a front end for parsing the document syntax and transforming it into an internal standardised form. This means that on this layer one should not see any (or not much) coding or computation.
+
+It is envisioned that alternative document syntax models can be provided.
+At the moment we have a draft solution in \pkg{xparse}.
+This package offers a document syntax in the style of \LaTeXe, that is with \verb|*|-forms, optional arguments in brackets, etc., but with a few more bells and whistles such as a more generalized concept of default values, support for additional delimiters for arguments, verbatim-style arguments, and so on.
+It is fairly conventional though.
+In addition when it was written the clear separation of layers wasn't well-defined and so the package also contains components for conditional programming that I no longer think should be there.
+
+Bottom line on what is needed for this layer is to
+\begin{itemize}
+\item think about good syntax for providing document content from "the author" perspective
+\item think about good syntax for providing document content from an "application to typesetting" perspective, i.e., the syntax and structure for automated typesetting where the content is prepared by a system/application rather than by a human
+\end{itemize}
+These two areas most likely need strict structure (as automation works much better with structures that do not have a lot of alternative possibilities and shortcuts, etc.) and even when just looking at the human author a lot of open questions need answering.
+And these answers may or may not be to painfully stick with existing \LaTeXe\ conventions in all cases (or perhaps with any?).
+
+None of this requires coding or \pkg{expl3} experience. What it requires is familiarity with existing input concepts, a feel for where the pain points currently are and the willingness to think and discuss what alternatives and extensions could look like.
+
+\subsection{In Summary}
+
+Basically help is possible on any level and it doesn't need to involve programming. Thoughts are sprinkled throughout this article, but here are a few more highlights:
+\begin{itemize}
+\item help with developing/improving the core programming layer by
+\begin{itemize}[nosep]
+\item joining the effort to improve the test suite
+\item help improving the existing (or not existing) documentation
+\item joining the effort to produce core or auxiliary code modules
+\end{itemize}
+\item help on the design layer by
+\begin{itemize}[nosep]
+\item collecting and classifying design tasks
+\item thinking and suggesting ways to describe layout requirements in a declarative manner
+\end{itemize}
+\item help on shaping the document interface layer
+\end{itemize}
+These concepts, as well as their implementation, are under discussion on the list \texttt{latex-l}.\footnote{Instructions for joining and browsing archives at:\\ \url{http://latex-project.org/code.html}}
+The list has only a fairly low level of traffic right now as actual implementation and development tasks are typically discussed directly among the few active implementors. But this might change if more people join.
+
+\subsection{And something else \dots}
+
+The people on the \LaTeX3 team are also committed to keeping \LaTeXe\ stable and even while there isn't that much to do these days there remains the need to resolve bug reports (if they concern the 2e core), provide new distributions once in a while, etc. All this is work that takes effort or remains undone or incomplete. Thus here too, it helps the \LaTeX3 efforts if we get help to free up resources.
+
+\end{document}
+
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news09.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,220 @@
+% Copyright 2016 The LaTeX3 Project
+\documentclass{ltnews}
+
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{csquotes}
+\usepackage{hologo}
+\usepackage{ragged2e}
+\usepackage{underscore}
+
+\AtBeginDocument{%
+  \renewcommand*{\LaTeXNews}{\LaTeX3~News}%
+  \RaggedRight
+  \setlength\parindent{1em}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\publicationmonth{November}
+\publicationyear{2016}
+\publicationissue{10}
+
+% Avoid hyphenation of csnames
+\makeatletter
+\protected\edef\cs#1{%
+  \noexpand\path{\@backslashchar#1}%
+}
+\makeatother
+
+\begin{document}
+
+\maketitle
+
+There has been something of a gap since the last \LaTeX3 News, but this does
+not mean that work has not been going on. The Team have been working on a
+number of areas, many of which reflect wider take-up of \pkg{expl3}. There have
+also been a number of significant new developments in the \LaTeX3
+\enquote{sphere} in the last two years.
+
+\section{\pkg{l3build}: Testing \LaTeX{} packages}
+
+Testing has been an important part of the work of the team since they assumed
+maintenance of \LaTeX{} over twenty years ago. Various scripts have been used
+over that time by the team for testing, but these have until recently not been
+set up for wider use.
+
+With the general availability of \hologo{LuaTeX} it is now possible to be sure
+that every \TeX{} user has a powerful general scripting language available:
+Lua. The team have used this to create a new general testing system for \TeX{}
+code, \pkg{l3build}. This \emph{is} designed to be used beyond the team, so is
+now available in \TeX{} Live and \hologo{MiKTeX} and is fully documented.
+Testing using \pkg{l3build} makes use of a normalised version of the
+\texttt{.log} file, so can test any aspect of \TeX{} output (e.g., by using
+\cs{showbox}) or its algorithms (by displaying results in the \texttt{.log}).
+
+Part of the remit for creating \pkg{l3build} was to enable the team to work
+truly cross-platform and to allow testing using multiple \TeX{} engines
+(earlier systems were limited to a single engine, normally \eTeX{}). The new
+testing system means we are in a much stronger position to support a variety of
+engines (see below). It has also enabled us to give useful feedback on
+development of the \hologo{LuaTeX} engine.
+
+As well as the core capability in testing, \pkg{l3build} also provides a
+\enquote{one stop} script for creating release bundles. The script is
+sufficiently flexible that for many common \LaTeX{} package structures, setting
+up for creating releases will require only a few lines of configuration.
+
+In addition to the documentation distributed with \pkg{l3build}, the project
+website~\cite[publications in 2014]{10:project-publications} contains some
+articles, videos and conference presentations that explain how to use
+\pkg{l3build} to manage and test any type of (\LaTeX{}) package.
+
+\section{Automating \pkg{expl3} testing}
+
+As well as developing \pkg{l3build} for local use, the team have also set up
+integration testing for \pkg{expl3} using the Travis-CI system. This means that
+\emph{every} commit to the \LaTeX3 code base now results in a full set of tests
+being run. This has allowed us to significantly reduce the number of occasions
+where \pkg{expl3} needs attention before being released to CTAN.
+
+Automated testing has also enabled us to check that \pkg{expl3} updates do not
+break a number of key third-party packages which use the programming
+environment.
+
+\section{Refining \pkg{expl3}}
+
+Work continues to improve \pkg{expl3} both in scope and robustness. Increased
+use of the programming environment means that code which has to-date been
+under-explored is being used, and this sometimes requires changes to the code.
+
+The team have extended formal support in \pkg{expl3} to cover the engines
+p\TeX{} and up\TeX{}, principally used by Japanese \TeX{} users. This has been
+possible in part due to the \pkg{l3build} system discussed above.
+Engine-dependent variations between \hologo{pdfTeX}, \hologo{XeTeX},
+\hologo{LuaTeX} and (u)p\TeX{} are now well-understood and documented. As part
+of this process, the \enquote{low-level} part of \pkg{expl3}, which saves all
+primitives, now covers essentially all primitives found in all of these
+engines.
+
+The code in \pkg{expl3} is now entirely self-contained, loading no other
+third-party packages, and can also be loaded as a generic package with plain
+\TeX{}, \emph{etc.} These changes make it much easier to diagnose problems and
+make \pkg{expl3} more useful. In particular it can be used as a programming
+language for generic packages, that then can run without modifications under
+different formats!
+
+The team have made a range of small refinements to both internals and
+\pkg{expl3} interfaces. Internal self-consistency has also been improved, for
+example removing almost all use of \texttt{nopar} functions. Performance
+enhancements to the \pkg{l3keys} part of \pkg{expl3} are ongoing and should
+result in significantly faster key setting. As keyval methods are increasingly
+widely used in defining behaviours, this will have an impact on compile times
+for end users.
+
+\section{Replacing \cs{lowercase} and \cs{uppercase}}
+
+As discussed in the last \LaTeX3 News, the team have for some time been keen to
+provide new interfaces which do not directly expose (or in some cases even use)
+the \TeX{} primitives \cs{lowercase} and \cs{uppercase}. We have now created a
+series of different interfaces that provide support for the different
+conceptual uses which may flow from the primitives:
+\begin{itemize}
+  \item For case changing text, \cs{tl_upper_case:n}, \cs{tl_lower_case:n},
+    \cs{tl_mixed_case:n} and related language-aware functions. These are
+    Unicode-capable and designed for working with text. They also allow for
+    accents, expansion of stored text and leaving math mode unchanged.  At
+    present some of the interface decisions are not finalised so they are
+    marked as experimental, but the team expect the core concept to be stable.
+  \item For case changing programming strings, \cs{str_upper_case:n},
+    \cs{str_lower_case:n} and \cs{str_fold_case:n}. Again these are
+    Unicode-aware, but in contrast to the functions for text are not
+    context-dependent. They are intended for caseless comparisons, constructing
+    command names on-the-fly and so forth.
+  \item For creating arbitrary character tokens, \cs{char_generate:nn}. This
+    is based on the \cs{Ucharcat} primitive introduced by \hologo{XeTeX}, but
+    with the ideas extended to other engines. This function can be used to
+    create almost any reasonable token.
+  \item For defining active characters, \cs{char_set_active_eq:NN} and
+    related functions. The concept here is that active characters should be
+    equivalent to some named function, so one does not directly define the
+    active character.
+\end{itemize}
+
+\section{Extending \pkg{xparse}}
+
+After discussions at TUG2015 and some experimentation, the team have added a
+new argument type, \texttt{e} (\enquote{embellishment}), to \pkg{xparse}.
+This allows arguments similar to
+\TeX{} primitive sub- and superscripts to be accepted. Thus
+\begin{verbatim}
+\DeclareDocumentCommand\foo{e{^_}}
+  {\showtokens{"#1"}}
+\foo^{Hello} world
+\end{verbatim}
+will show
+\begin{verbatim}
+"{Hello}{-NoValue-}".
+\end{verbatim}
+
+At present, this argument type is experimental: there are a number of models
+which may make sense for this interface.
+
+\section{A new \cs{parshape} model}
+
+As part of development of \pkg{l3galley}, Joseph Wright has proposed a new
+model for splitting up the functions of the \cs{parshape} primitive into three
+logical elements:
+\begin{itemize}
+  \item Margins between the edges of the galley and the paragraph (for example
+    an indented block);
+  \item Cut-out sections running over a fixed number of lines, to support
+    \enquote{in place} figures and so forth;
+  \item Running or single-paragraph shape.
+\end{itemize}
+
+There are additional elements to consider here, for example whether lines are
+the best way to model the length of shaping, how to handle headings, cut-outs
+at page breaks, \emph{etc.}
+
+
+\section{Globally optimized pagination of documents}
+
+Throughout 2016 Frank Mittelbach has worked on methods and algorithms for
+globally optimizing the pagination of documents including those that contain
+floats. Early research results have been presented at Bacho\TeX{} 2016, TUG
+2016 in Toronto and later in the year at \mbox{DocEng'16}, the ACM Symposium on
+Document Engineering in Vienna. A link to the ACM paper (that allows a download
+free of charge) can be found on the project
+website~\cite{10:project-publications}. The site also holds the speaker notes from
+Toronto and will host a link to a video of the presentation once it becomes
+available.
+
+The framework developed by Frank is based on the extended functionality
+provided by \hologo{LuaTeX}, in particular its callback functions that allow
+interacting with the typesetting process at various points. The algorithm that
+determines the optimal pagination of a given document is implemented in {Lua}
+and its results are then used to direct the formatting done by the \TeX{}
+engine.
+
+At the current point in time this a working prototype but not yet anywhere near
+a production-ready system. However, the work so far shows great potential and
+Frank is fairly confident that it will eventually become a generally usable
+solution.
+
+\section{Looking forward}
+
+The \hologo{LuaTeX} engine has recently reached version~1.0. This may presage a
+stable \hologo{LuaTeX} and is likely to result in wider use of this engine in
+production documents.If that happens we expect to implement some of the more
+complex functionality (such as complex pagination requirements and models) only
+for \hologo{LuaTeX}.
+
+\begin{thebibliography}{10}
+  \raggedright
+  \bibitem{10:project-publications}
+    Links to various publications by members of the \LaTeX{} Project Team.
+    \newblock \url{https://www.latex-project.org/publications}.
+\end{thebibliography}
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news10.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,208 @@
+% Copyright 2017-2018 The LaTeX3 Project
+
+\documentclass{ltnews}
+
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+\usepackage{csquotes}
+\usepackage{hologo}
+\usepackage{ragged2e}
+\usepackage{underscore}
+
+
+%%% wrong in ltnews.cls ... so some tmp fix here at the moment:
+\makeatletter
+\renewcommand{\subsubsection}{%
+   \@startsection
+      {subsubsection}{2}{\leftmargini}{-1.5ex \@plus -1ex \@minus -.2ex}%
+      {1sp}{\@subheadingfont}%
+}
+\makeatother
+
+
+\AtBeginDocument{%
+  \renewcommand*{\LaTeXNews}{\LaTeX3~News}%
+  \RaggedRight
+  \setlength\parindent{1em}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\publicationmonth{February}
+\publicationyear{2018}
+\publicationissue{11}
+
+% Avoid hyphenation of csnames
+\makeatletter
+\protected\edef\cs#1{%
+  \noexpand\path{\@backslashchar#1}%
+}
+\makeatother
+\hyphenpenalty=10000 \exhyphenpenalty=10000
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\section{Move of sources from Subversion to Git}
+
+The \LaTeX{} team have used a variety of version control systems over the life
+of the \LaTeX3 sources. For a long time we maintained the \LaTeX3 sources in
+Subversion (\texttt{svn}) but also provided a read-only clone of them on GitHub using
+SubGit from TMate Software~\cite{SubGit} to synchronize the two
+repositories---a solution that worked very well.
+
+We have now retired the Subversion repository and completely moved over to Git,
+with the master \LaTeX3 repository hosted on GitHub:
+\url{https://github.com/latex3/latex3}. This new approach means we are (slowly)
+adopting some new approaches to development, for example branches and accepting
+pull requests.
+
+\subsection{Version identifiers}
+
+Following this change, we have removed Subversion \verb=$Id= lines from the
+\LaTeX3 sources. At present, we will be retaining \cs{GetIdInfo} as there are
+several possible use cases. The \LaTeX3 sources now have only release date
+strings as identifiers. However, the team recommend that package authors
+include version information directly in \cs{ProvidesExplPackage} (or similar)
+lines.
+
+\section{\pkg{expl3} updates and extensions}
+
+Work has continued on the codebase over the last year, with both small
+changes/fixes and more substantial changes taking place. The following sections
+summarise some of the more notable changes.
+
+\subsection{\pkg{l3sort} moves to the kernel}
+
+Sorting is an important ability, and for some time the team have provided a
+stand-alone \pkg{l3sort} to support this. The functionality has seen wide take
+up, and so has now been integrated directly into the kernel. This took place in
+parallel with some interface changes to \enquote{round out} the code.
+
+\subsection{Boolean functions}
+
+For some time, the team have been aware that boolean expressions can fail in
+certain circumstances, leading to low-level errors. This is linked to two
+features of the long-standing \cs{bool_if:n(TF)} function: expandable operation
+and short-circuit evaluation.
+
+Addressing that has meant two changes: altering \cs{bool_if:n(TF)} to
+\emph{always} evaluate each part of the expression, and introducing new
+short-circuit functions without the issue. The latter are \verb|lazy| in \pkg{expl3}
+terms:
+\begin{itemize}
+\item \cs{bool_lazy_all:n(TF)}
+\item \cs{bool_lazy_and:nn(TF)}
+\item \cs{bool_lazy_any:n(TF)}
+\item \cs{bool_lazy_or:nn(TF)}
+\end{itemize}
+These new, stable functions are now the recommended way of handling boolean
+evaluations. Package authors are encouraged to employ these new functions as
+appropriate.
+
+\subsection{Revision of \pkg{l3file}}
+
+Large parts of \pkg{l3file} have been revised to give a better separation of
+path/file/extension. This has resulted in the addition of a number of new support
+functions and variables.
+
+At the same time, new experimental functions have been added to utilise a
+number of useful primitives in \hologo{pdfTeX}{}: \cs{file_get_mdfive_hash:nN},
+\cs{file_get_size:nN} and \cs{file_get_timestamp:nN}. Currently, \hologo{XeTeX}
+does not support getting file size/timestamp information: this is available in
+other engines.
+
+Paralleling these changes, we have added (experimental) support for shell
+escape to the \pkg{l3sys} module, most notably \cs{sys_shell_now:n}. A range of
+test booleans are also available to check whether shell escape is enabled.
+
+\subsection{Detection of \cs{cs_generate_variant:Nn} errors}
+
+The ability to generate variants is an important feature of \pkg{expl3}. At
+the same time,  there are crucial aspects of this approach that can be
+misunderstood by users. In particular, the requirement that variants map
+correctly to an underlying \verb|N|- or \verb|n|-type base function is sometimes
+misunderstood.
+
+To help detect and correct these cases, \cs{cs_generate_variant:Nn} now
+carries out error checking on its arguments, and raises a warning where
+it is mis-applied. At present, the team have avoided making this an error
+as it is likely to be seen by end users rather than directly by package
+developers. In time, we are likely to revisit this and tighten up
+further on this key requirement.
+
+\subsection{Accessing random data}
+
+To support randomised data selection, we have introduced a family of
+experimental functions which use under\-lying engine support for random values,
+and provide one entry at random from the data type.
+
+At the same time, we have addressed some issues with uniformity stemming from
+the random number function used by \hologo{pdfTeX}{} and inherited by other
+engines. This means that \pkg{expl3}'s FPU will generate \emph{pseudo}-random
+values across the range of possible outputs.
+
+\subsection{More powerful debugging}
+
+A new set of debugging functions have been added to the kernel. These allow
+debug code to be enabled locally using the new option \verb|enable-debug| along
+with functions \cs{debug_on:n} and \cs{debug_off:n}. Accompanying this change, we
+have improved the handling of global/local consistency in variable setting.
+
+\subsection{Mark-up changes in \pkg{l3doc}}
+
+Since the introduction of the \verb|__| syntax to mark internal functions, the
+need for explicit markup of internal material in sources has been negated.
+As such, we have now dropped the requirement to mark internal material with
+\verb|[aux]| when using \pkg{l3doc}. Instead, the status of functions and
+variables is auto-detected from the presence of \verb|__|. For cases where
+non-standard names are used for internal code, the mark-up \verb|[int]| is
+retained, \emph{e.g.}
+\begin{verbatim}
+\begin{macro}[int]{\l at expl@enable at debug@bool}
+\end{verbatim}
+
+\newpage
+\section{\pkg{l3build} updates}
+
+Work on \pkg{l3build} has continued in parallel with \pkg{expl3} work, in
+particular continuing to develop features to allow wider use of the tool.
+
+Paralleling the move of the \LaTeX3 codebase to Git, \pkg{l3build} now has its
+own separate Git repository: \url{https://github.com/latex3/l3build}. This will
+enable us to involve other developers in the Lua code required for the build
+system. At the same time, we have split the code into a number of small source
+files, again to ease development both for the team ourselves and for potential
+collaborators.
+
+Another major change is that \pkg{l3build} can now retain the structure of
+source repositories when creating a CTAN archive. Whilst the team favor `flat'
+source setups, other users prefer structured approaches. Most notably, this
+new \pkg{l3build} functionality means that it is now used to carry out
+\pkg{beamer} releases.
+
+The other major new feature is a new approach to multiple test setups, which
+replaces the older \verb|--testfiledir| option. In the new approach, separate
+configuration files are listed in the main \verb|build.lua| script, and can be
+selected manually using a new \verb|--config| switch. This new approach allows
+complex test setups to be run in a totally automated fashion, which is
+important for kernel testing.
+
+Some changes to the normalisation routines have been carried out, some to deal
+with upcoming \hologo{LuaTeX} changes, others to address aspects which show up
+only in some tests. This has required \verb|.tlg| updates in some cases: as far
+as possible, we strive to avoid requiring changes to the reference files.
+
+\begin{thebibliography}{10}
+  \raggedright
+  \bibitem{SubGit}
+    \emph{SubGit}, TMate Software, \url{https://subgit.com}
+  \bibitem{11:project-publications}
+    Links to various publications by members of the \LaTeX{} Project Team.
+    \newblock \url{https://www.latex-project.org/publications}
+\end{thebibliography}
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news11.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,383 @@
+% Copyright 2019 The LaTeX3 Project
+\documentclass{ltnews}
+
+\usepackage{csquotes}
+\usepackage{hologo}
+\usepackage{ragged2e}
+
+\PassOptionsToPackage{colorlinks}{hyperref}
+
+%%% wrong in ltnews.cls ... so some tmp fix here at the moment:
+\makeatletter
+\renewcommand{\subsubsection}{%
+   \@startsection
+      {subsubsection}{2}{\leftmargini}{-1.5ex \@plus -1ex \@minus -.2ex}%
+      {1sp}{\@subheadingfont}%
+}
+\makeatother
+
+\AtBeginDocument{%
+  \renewcommand*{\LaTeXNews}{\LaTeX3~News}%
+  \RaggedRight
+  \setlength\parindent{1em}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\publicationmonth{January}
+\publicationyear{2020}
+\publicationissue{12}
+
+% Avoid hyphenation of csnames
+\makeatletter
+\protected\edef\cs#1{%
+  \noexpand\path{\@backslashchar#1}%
+}
+\makeatother
+\hyphenpenalty=10000
+\exhyphenpenalty=10000
+\hbadness=2500
+
+\makeatletter
+\renewcommand*\l at section[2]{%
+  \ifnum \c at tocdepth >\z@
+    \addpenalty\@secpenalty
+    \addvspace{0.7em \@plus\p@}% reduce from 1.0em
+    \setlength\@tempdima{1.5em}%
+    \begingroup
+      \parindent \z@ \rightskip \@pnumwidth
+      \parfillskip -\@pnumwidth
+      \leavevmode \bfseries
+      \advance\leftskip\@tempdima
+      \hskip -\leftskip
+      #1\nobreak\hfil
+      \nobreak\hb at xt@\@pnumwidth{\hss #2%
+                                 \kern-\p@\kern\p@}\par
+    \endgroup
+  \fi}
+\makeatother
+
+\newenvironment{compactitemize}%
+   {\begin{itemize}%
+     \setlength{\itemsep}{0pt}%
+     \setlength{\parskip}{0pt}%
+     \setlength{\parsep} {0pt}%
+   }%
+   {\end{itemize}}
+
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\section{Introduction}
+
+There has been quite a gap since the last \emph{\LaTeX3 News} (Issue~11,
+February 2018), and so there is quite a bit to cover here. Luckily, one of the
+things there \emph{is} to cover is that we are using a more formalised approach
+for logging changes, so writing up what has happened is a bit easier.
+(By mistake \LaTeX3 News~11 itself did not get \emph{published} when written, but is
+now available: we have kept the information it contains separate as it
+is a good summary of the work that had happened in 2017.)
+
+Work has continued apace across the \LaTeX3 codebase in the last (nearly) two
+years. A lot of this is ultimately focussed on making the core of \pkg{expl3}
+even more stable: \emph{squeezing} out more experimental ideas, refining
+ones we have and making it a serious option for core \LaTeX{} programming.
+
+As a result of these activities, the \LaTeX3 programming layer will be
+available as part of the kernel of \LaTeXe{} from 2020-02-02 onwards, i.e., can
+be used without explicitly loading \pkg{expl3}. See \emph{\LaTeX{}
+  News~31}~\cite{12:site-news} for more details on this.
+
+\section{New features in \pkg{expl3}}
+
+\subsection{A new argument specifier: \texttt{e}-type}
+
+During 2018, the team worked with the \TeX{} Live, \hologo{XeTeX} and
+(u)p\TeX{} developers to add the \cs{expanded} primitive to \hologo{pdfTeX}{},
+\hologo{XeTeX} and (u)p\TeX{}. This primitive was originally suggested for
+\hologo{pdfTeX}{} v1.50 (never released), and was present in \hologo{LuaTeX}{}
+from the start of that project.
+
+Adding \cs{expanded} lets us create a new argument specifier: \texttt{e}-type
+expansion. This is \emph{almost} the same as \texttt{x}-type, but is itself
+expandable. (It also doesn't need doubled \verb|#| tokens.) That's incredibly
+useful for creating function-like macros: you can ensure that \emph{everything}
+is expanded in an argument before you go near it, with not an \cs{expandafter}
+in sight.
+
+\subsection{New functions}
+
+New programming tools have appeared in various places across \pkg{expl3}.
+The highlights are
+\begin{compactitemize}
+  \item Shuffling of sequences to allow randomization
+  \item Arrays of integers and floating point values; these have constant-time
+    access
+  \item Functions to return values after system shell usage
+  \item Expandable access to file information, including file size, MD5
+    hash and modification date
+\end{compactitemize}
+
+For the latter, we have revised handling of file names considerably. There is
+now support for finding files in expansion contexts (by using the
+\cs{(pdf)filesize} primitive). Spaces and quotes in file names are now fully
+normalised, in a similar manner to the approach used by the latest \LaTeXe{}
+kernel.
+
+\subsection{String conversion moves to \pkg{expl3}}
+
+In addition to entirely new functions, the team have moved the
+\pkg{l3str-convert} module from the \pkg{l3experimental} bundle into the
+\pkg{expl3} core. This module is essential for dealing with the need to produce
+UTF-16 and UTF-32 strings in some contexts, and also offers
+built-in escape for url and PDF strings.
+
+\subsection{Case changing of text}
+
+Within \pkg{expl3}, the team have renamed and reworked the ideas from
+\cs{tl_upper_case:n} and so on, creating a new module \pkg{l3text}. This is a
+\enquote{final} home for functions to manipulate \emph{text}; token lists that
+can reasonably be expected to expand to plain text plus limited markup, for
+example emphasis and labels/references. Moving these functions, we have also
+made a small number of changes in other modules to give consistent names to
+functions: see the change log for full details.
+
+Over time, we anticipate that functions for other textual manipulation will be
+added to this module.
+
+\section{Notable fixes and changes}
+
+\subsection{File name parsing}
+
+The functions for parsing file names have been entirely rewritten, partly as
+this is required for the expandable access to file information mentioned above.
+The new code correctly deals with spaces and quote marks in file names and
+splits the path/name/extension.
+
+\subsection{Message formatting}
+
+The format of messages in \pkg{expl3} was originally quite text-heavy, the idea
+being that they would stand out in the \texttt{.log} file. However, this made
+them hard to find by a regular expression search, and was very different from
+the \LaTeXe{} message approach. The formatting of \pkg{expl3} messages has been
+aligned with that from the \LaTeXe{} kernel, such that IDE scripts and
+similar will be able to find and extract them directly.
+
+\subsection{Key inheritance}
+
+A number of changes have been made to the inheritance code for keys,
+to allow inheritance to work \enquote{as expected} in (almost) all
+cases.
+
+\subsection{Floating point juxtaposition}
+
+Implicit multiplication by juxtaposition, such as \verb|2pi|, is now handled
+separately from parenthetic values. Thus for example \verb|1in/1cm| is treated
+as equal to \verb|(1in)/(1cm)| and thus yields \verb|2.54|, and \verb|1/2(pi+pi)| is
+equal to \verb|pi|.
+
+\subsection{Changing box dimensions}
+
+\TeX{}'s handling of boxes is subtly different from other registers, and this
+shows up in particular when you want to resize a box. To bring treatment of
+boxes, or rather the grouping behavior of boxes, into line with other
+registers, we have made some internal changes to how functions such as
+\cs{box_set_wd:N} are implemented. This will be transparent for
+\enquote{well-behaved} use cases of these functions.
+
+\subsection{More functions moved to stable}
+
+A large number of functions which were introduced as candidates have been
+evaluated and moved to stable status. The team hopes to move all functions
+in \pkg{expl3} to stable status, or move them out of the core, over the coming
+months.
+
+\subsection{Deprecations}
+
+There have been two notable sets of deprecations over the past 18 months.
+First, we have rationalised all of the \enquote{raw} primitive names to the
+form \cs{tex_<name>:D}. This means that the older names, starting
+\mbox{\cs{pdftex_...}}, \cs{xetex_...}, etc., have been removed.
+
+Secondly, the use of integer constants, which dates back to the earliest days
+of \pkg{expl3}, is today more likely to make the code harder to read than
+anything else. Speed improvements in engines mean that the tiny enhancements in
+reading such constants are no longer required. Thus for example \cs{c_two} is
+deprecated in favour of simply using \texttt{2}.
+
+In parallel with this, a number of older \texttt{.sty} files have been removed.
+These older files provided legacy stubs for files which have now been
+integrated in the \pkg{expl3} core. They have now had sufficient time to allow
+users to update their code.
+
+\section{Internal improvements}
+
+\subsection{Cross-module functions}
+
+The team introduced the idea of internal module functions some time ago. Within
+the kernel, there are places where functions need to be used in multiple
+modules. To make the nature of the kernel interactions clearer, we have worked
+on several aspects
+\begin{compactitemize}
+  \item Reducing as far as possible cross-module functions
+  \item Making more generally-useful functions public, for example
+    scan marks
+  \item Creating an explicit cross-kernel naming convention for
+    functions which are internal but are essential to use in multiple
+    kernel modules
+\end{compactitemize}
+
+\subsection{The backend}
+
+Creating graphics, working with color, setting up hyperlinks and so on require
+backend-specific code. Here, backends are for example \texttt{dvips},
+\texttt{xdvipdfmx} and the direct PDF mode in \hologo{pdfTeX} and
+\hologo{LuaTeX}. These functions are needed across the \LaTeX3 codebase and
+have to be updated separately from the \pkg{expl3} core. To facilitate that, we
+have split those sources into a separate bundle, which can be updated as
+required.
+
+At the same time, the code these files contain is very low-level and is best
+described as internal. We have re-structured how the entire set of functions
+are referred to such that they are now internal for the area they implement,
+for example image inclusion, box affine transformations, etc.
+
+\section{Better support for (u)p\texorpdfstring{\kern-.05em}{}\TeX{}}
+
+The developers behind (u)p\TeX{} (Japanese \TeX{}) have recently enhanced their
+English documentation (see \url{https://github.com/texjporg/ptex-manual}).
+Using this new information, we have been able to make internal adjustments to
+\pkg{expl3} to better support these engines.
+
+\section{Options}
+
+A new option \texttt{undo-recent-deprecations} is now available for cases where
+a document (or package) requires some \pkg{expl3} functions that have been
+formally removed after deprecation. This is to allow \emph{temporary}
+work-arounds for documents to be compiled whilst code is begin updated.
+
+The \enquote{classical} options for selecting backends (\texttt{dvips},
+\texttt{pdftex}, etc.)\ are now recognised in addition to the native key--value
+versions. This should make it much easier to use the \pkg{expl3} image and color
+support as it is brought up to fully-workable standards.
+
+\section{Engine requirements}
+
+The minimum engine versions needed to use \pkg{expl3} have been
+incremented a little:
+\begin{compactitemize}
+  \item \hologo{pdfTeX} v1.40
+  \item \hologo{XeTeX} v0.99992
+  \item \hologo{LuaTeX} v0.95
+  \item $\varepsilon$-(u)p\TeX{} mid-2012
+\end{compactitemize}
+
+The team have also worked with the \hologo{XeTeX} and (u)p\TeX{} developers to
+standardise the set of post-\eTeX{} utility primitives that are available: the
+so-called \enquote{\hologo{pdfTeX} utilities}. These are now available in all
+supported engines, and in time will all be \emph{required}. This primarily
+impacts \hologo{XeTeX}, which gained most of these primitives in the 2019
+\TeX{} Live cycle. (Examples are the random number primitives and expandable
+file data provision.) See \emph{\LaTeX{} News~31}~\cite{12:site-news}
+for more.
+
+\section{Documentation}
+
+\subsection{News}
+
+The \emph{\LaTeX3 News} files were until recently only used to create
+PDF files on the team website~\cite{12:site}. We have now
+integrated those into the \pkg{l3kernel} (\pkg{expl3} core)
+bundle. The news files cover all of \LaTeX3 files, as the core files
+are always available.
+
+\subsection{ChangeLog}
+
+Since the start of 2018, the team have commenced a comprehensive
+change log for each of the bundles which make up the \LaTeX3 code.
+These are simple Markdown text files, which means that they can be displayed
+formatted in web views.
+
+\section{Changes in \pkg{xparse}}
+
+A number of new features have been added to \pkg{xparse}. To allow
+handling of the fact that skipping spaces may be required only in
+some cases when searching for optional arguments, a new modifier
+\texttt{!} is available in argument specifiers. This causes
+\pkg{xparse} to \emph{require} that an optional argument follows
+immediately with no intervening spaces.
+
+There is a new argument type purely for environments: \texttt{b}-type
+for collecting a \cs{begin}\texttt{...}\cs{end} pair, i.e., collecting the body of
+an environment. This is similar in concept to the \pkg{environ} package,
+but is integrated directly into \pkg{xparse}.
+
+Finally, it is now possible to refer to one argument as the
+default for another optional one, for example
+\begin{verbatim}
+\NewDocumentCommand{\caption}{O{#2} m} ...
+\end{verbatim}
+
+\section{New experimental modules}
+
+A number of new experimental modules have been added within the
+\pkg{l3experimental} bundle:
+\begin{description}
+  \item[\pkg{l3benchmark}] Performance-testing system using the timing
+    function in modern \TeX{} engines
+  \item[\pkg{l3cctab}] Category code tables for all engines, not
+    just \hologo{LuaTeX}
+  \item[\pkg{l3color}] Color support, similar in interface to \pkg{xcolor}
+  \item[\pkg{l3draw}] Creation of drawings, inspired by \pkg{pgf}, but
+    using the \LaTeX3 FPU for calculations
+  \item[\pkg{l3pdf}] Support for PDF features such as compression,
+    hyperlinks, etc.
+  \item[\pkg{l3sys-shell}] Shell escape functions for file manipulation
+\end{description}
+
+\section{\pkg{l3build} changes}
+
+The \pkg{l3build} tool for testing and releasing \TeX{} packages
+has seen a number of incremental improvements. It is now available directly
+as a script in \TeX{} Live and MiK\TeX{}, meaning you can call it simply
+as
+\begin{verbatim}
+l3build <target>
+\end{verbatim}
+Accompanying this, we have added support for installing scripts and script
+\texttt{man} files.
+
+There is a new \texttt{upload} target that can take a zip file and send it to
+CTAN: you just have to fill in release information for \emph{this}
+upload at the prompts.
+
+Testing using PDF files rather than logs has been heavily revised:
+this is vital for work on PDF tagging.
+
+There is also better support for complex directory structures, including the
+ability to manually specify TDS location for all installed files. This
+is particularly targeted at packages with both generic and format-specific files
+to install.
+
+
+\begin{thebibliography}{9}
+
+\fontsize{9.9}{11.9}\selectfont
+
+
+\bibitem{12:site}
+  \emph{\LaTeX{} Project Website}.
+  \hfil\break\url{https://latex-project.org/}
+
+\bibitem{12:site-news}
+  \emph{\LaTeXe{} release newsletters on the \LaTeX{} Project Website}.
+  \url{https://latex-project.org/news/latex2e-news/}
+
+  
+\end{thebibliography}
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3news12.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3obsolete.txt
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3obsolete.txt	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3obsolete.txt	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,743 @@
+This file lists functions and variables which were part of l3kernel
+but which are either deprecated or which have been removed entirely.
+The file is split into two parts. The first part lists functions
+which are deprecated but are still currently included in the
+extracted files. The second part lists functions which have been
+removed from the distribution entirely. Functions which were added
+with 'experimental' status only are not listed.
+
+Deprecated functions and variables
+==================================
+
+These functions are deprecated and should be removed from packages.
+
+---------------------------------------------------
+Function                            Date deprecated
+---------------------------------------------------
+\char_fold_case:N                        2020-01-03
+\char_foldcase:N                         2022-10-17
+\char_lower_case:N                       2020-01-03
+\char_lowercase:N                        2022-10-17
+\char_mixed_case:N                       2020-01-03
+\char_titlecase:N                        2022-10-17
+\char_upper_case:N                       2020-01-03
+\char_uppercase:N                        2022-10-17
+\char_str_fold_case:N                    2020-01-03
+\char_str_foldcase:N                     2022-10-17
+\char_str_lower_case:N                   2020-01-03
+\char_str_lowercase:N                    2022-10-17
+\char_str_mixed_case:N                   2020-01-03
+\char_str_titlecase:N                    2022-10-17
+\char_str_upper_case:N                   2020-01-03
+\char_str_uppercase:N                    2022-10-17
+\char_to_utfviii_bytes:n                 2022-10-09
+\char_to_nfd:N                           2022-10-09
+\cs_argument_spec:N                      2022-06-24
+\iow_shipout_x:cn                        2023-09-17
+\iow_shipout_x:cx                        2023-09-17
+\iow_shipout_x:Nn                        2023-09-17
+\iow_shipout_x:Nx                        2023-09-17
+\keys_set_filter:nnn                     2024-01-10
+\keys_set_filter:nnV                     2024-01-10
+\keys_set_filter:nnv                     2024-01-10
+\keys_set_filter:nno                     2024-01-10
+\keys_set_filter:nnnN                    2024-01-10
+\keys_set_filter:nnVN                    2024-01-10
+\keys_set_filter:nnvN                    2024-01-10
+\keys_set_filter:nnoN                    2024-01-10
+\keys_set_filter:nnnnN                   2024-01-10
+\keys_set_filter:nnVnN                   2024-01-10
+\keys_set_filter:nnvnN                   2024-01-10
+\keys_set_filter:nnonN                   2024-01-10
+\l_keys_key_tl                           2020-02-08
+\l_keys_path_tl                          2020-02-08
+\l_text_accents_tl                       2023-02-07
+\l_text_letterlike_tl                    2023-02-07
+\msg_gset:nnn                            2024-02-13
+\msg_gset:nnnn                           2024-02-13
+\peek_catcode_ignore_spaces:N            2022-01-11
+\peek_catcode_remove_ignore_spaces:N     2022-01-11
+\peek_charcode_ignore_spaces:N           2022-01-11
+\peek_charcode_remove_ignore_spaces:N    2022-01-11
+\peek_meaning_ignore_spaces:N            2022-01-11
+\peek_meaning_remove_ignore_spaces:N     2022-01-11
+\pdf_object_new:nn                       2022-08-23
+\pdf_object_write:nn                     2022-08-23
+\pdf_object_write:nx                     2022-08-23
+\prop_gput_if_new:cnn                    2024-03-30
+\prop_gput_if_new:cnV                    2024-03-30
+\prop_gput_if_new:cVn                    2024-03-30
+\prop_gput_if_new:Nnn                    2024-03-30
+\prop_gput_if_new:NnV                    2024-03-30
+\prop_gput_if_new:NVn                    2024-03-30
+\prop_put_if_new:cnn                     2024-03-30
+\prop_put_if_new:cnV                     2024-03-30
+\prop_put_if_new:cVn                     2024-03-30
+\prop_put_if_new:Nnn                     2024-03-30
+\prop_put_if_new:NnV                     2024-03-30
+\prop_put_if_new:NVn                     2024-03-30
+\str_declare_eight_bit_encoding:nnn      2020-08-20
+\str_fold_case:n                         2020-01-03
+\str_fold_case:V                         2020-01-03
+\str_foldcase:n                          2022-10-17
+\str_foldcase:V                          2022-10-17
+\str_lower_case:f                        2020-01-03
+\str_lower_case:n                        2020-01-03
+\str_upper_case:f                        2020-01-03
+\str_upper_case:n                        2020-01-03
+\seq_indexed_map_inline:Nn               2020-06-18
+\seq_indexed_map_function:NN             2020-06-18
+\seq_gset_map_x:NNn                      2023-10-26
+\seq_set_map_x:NNn                       2023-10-26
+\sys_load_deprecation:                   2021-01-11
+\text_titlecase:n                        2023-07-08
+\text_titlecase:nn                       2023-07-08
+\tl_build_clear:N                        2023-10-18
+\tl_build_gclear:N                       2023-10-18
+\tl_build_get:NN                         2023-12-14
+\tl_case:cn                              2023-05-23
+\tl_case:cnF                             2023-05-23
+\tl_case:cnT                             2023-05-23
+\tl_case:cnTF                            2023-05-23
+\tl_case:Nn                              2023-05-23
+\tl_case:NnF                             2023-05-23
+\tl_case:NnT                             2023-05-23
+\tl_case:NnTF                            2023-05-23
+\tl_lower_case:n                         2020-01-03
+\tl_lower_case:nn                        2020-01-03
+\tl_mixed_case:n                         2020-01-03
+\tl_mixed_case:nn                        2020-01-03
+\tl_upper_case:n                         2020-01-03
+\tl_upper_case:nn                        2020-01-03
+[key property] .str_gset_x:c             2023-09-27
+[key property] .str_gset_x:N             2023-09-27
+[key property] .str_set_x:c              2023-09-27
+[key property] .str_set_x:N              2023-09-27
+[key property] .tl_gset_x:c              2023-09-27
+[key property] .tl_gset_x:N              2023-09-27
+[key property] .tl_set_x:c               2023-09-27
+[key property] .tl_set_x:N               2023-09-27
+[x-type variants]                        2023-09-27
+---------------------------------------------------
+
+Removed functions and variables
+===============================
+
+The 'Date removed' column details when the functions were
+removed from the sources.
+
+----------------------------------------------------------
+Function                                      Date removed
+----------------------------------------------------------
+\box_gset_eq_clear:cc                           2021-07-07
+\box_gset_eq_clear:cN                           2021-07-07
+\box_gset_eq_clear:Nc                           2021-07-07
+\box_gset_eq_clear:NN                           2021-07-07
+\box_resize:cnn                                 2018-12-27
+\box_resize:Nnn                                 2018-12-27
+\box_set_eq_clear:cc                            2021-07-07
+\box_set_eq_clear:cN                            2021-07-07
+\box_set_eq_clear:Nc                            2021-07-07
+\box_set_eq_clear:NN                            2021-07-07
+\box_use_clear:c                                2018-12-27
+\box_use_clear:N                                2018-12-27
+\c_active_char_token                            2011-09-08
+\c_alignment_tab_token                          2011-09-08
+\c_eight                                        2020-01-01
+\c_eleven                                       2020-01-01
+\c_empty_toks                                   2011-09-08
+\c_fifteen                                      2020-01-01
+\c_five                                         2020-01-01
+\c_four                                         2020-01-01
+\c_fourteen                                     2020-01-01
+\c_term_ior                                     2021-07-07
+\c_job_name_tl                                  2017-01-01
+\c_keys_code_root_tl                            2013-01-08
+\c_letter_token                                 2011-09-08
+\c_luatex_is_engine_bool                        2011-12-30
+\c_math_shift_token                             2011-09-08
+\c_minus_one                                    2018-12-27
+\c_nine                                         2020-01-01
+\c_one                                          2020-01-01
+\c_one_hundred                                  2020-01-01
+\c_one_thousand                                 2020-01-01
+\c_other_char_token                             2011-09-08
+\c_pdftex_is_engine_bool                        2011-12-30
+\c_seven                                        2020-01-01
+\c_six                                          2020-01-01
+\c_sixteen                                      2020-01-01
+\c_string_cctab                                 2012-06-30
+\c_thirteen                                     2020-01-01
+\c_thirty_two                                   2020-01-01
+\c_three                                        2020-01-01
+\c_ten                                          2020-01-01
+\c_ten_thousand                                 2020-01-01
+\c_twelve                                       2020-01-01
+\c_two                                          2020-01-01
+\c_two_hundred_fifty_five                       2020-01-01
+\c_two_hundred_fifty_six                        2020-01-01
+\c_undefined_fp                                 2014-05-28
+\c_xetex_is_engine_bool                         2011-12-30
+\c_zero                                         2020-01-01
+\char_make_active:N                             2011-09-08
+\char_make_active:n                             2011-09-08
+\char_make_alignment_tab:N                      2011-09-08
+\char_make_alignment_tab:n                      2011-09-08
+\char_make_begin_group:N                        2011-09-08
+\char_make_begin_group:n                        2011-09-08
+\char_make_comment:N                            2011-09-08
+\char_make_comment:n                            2011-09-08
+\char_make_end_group:N                          2011-09-08
+\char_make_end_group:n                          2011-09-08
+\char_make_end_line:N                           2011-09-08
+\char_make_end_line:n                           2011-09-08
+\char_make_escape:N                             2011-09-08
+\char_make_escape:n                             2011-09-08
+\char_make_ignore:N                             2011-09-08
+\char_make_ignore:n                             2011-09-08
+\char_make_invalid:N                            2011-09-08
+\char_make_invalid:n                            2011-09-08
+\char_make_letter:N                             2011-09-08
+\char_make_letter:n                             2011-09-08
+\char_make_math_shift:N                         2011-09-08
+\char_make_math_shift:n                         2011-09-08
+\char_make_math_subscript:N                     2011-09-08
+\char_make_math_subscript:n                     2011-09-08
+\char_make_math_superscript:N                   2011-09-08
+\char_make_math_superscript:n                   2011-09-08
+\char_make_other:N                              2011-09-08
+\char_make_other:n                              2011-09-08
+\char_make_parameter:N                          2011-09-08
+\char_make_parameter:n                          2011-09-08
+\char_make_space:N                              2011-09-08
+\char_make_space:n                              2011-09-08
+\char_set_catcode:w                             2011-09-08
+\char_set_lccode:w                              2011-09-08
+\char_set_mathcode:w                            2011-09-08
+\char_set_sfcode:w                              2011-09-08
+\char_set_uccode:w                              2011-09-08
+\char_show_value_catcode:w                      2011-09-08
+\char_show_value_lccode:w                       2011-09-08
+\char_show_value_mathcode:w                     2011-09-08
+\char_show_value_sfcode:w                       2011-09-08
+\char_show_value_uccode:w                       2011-09-08
+\char_value_catcode:w                           2011-09-08
+\char_value_lccode:w                            2011-09-08
+\char_value_mathcode:w                          2011-09-08
+\char_value_sfcode:w                            2011-09-08
+\char_value_uccode:w                            2011-09-08
+\chk_if_free_cs:N                               2013-01-08
+\clist_display:c                                2011-09-08
+\clist_display:N                                2011-09-08
+\clist_gremove_element:Nn                       2011-09-08
+\clist_gtrim_spaces:c                           2011-12-20
+\clist_gtrim_spaces:N                           2011-12-20
+\clist_if_eq_p:cc                               2013-01-08
+\clist_if_eq:ccF                                2013-01-08
+\clist_if_eq:ccT                                2013-01-08
+\clist_if_eq:ccTF                               2013-01-08
+\clist_if_eq_p:cN                               2013-01-08
+\clist_if_eq:cNF                                2013-01-08
+\clist_if_eq:cNT                                2013-01-08
+\clist_if_eq:cNTF                               2013-01-08
+\clist_if_eq_p:Nc                               2013-01-08
+\clist_if_eq:NcF                                2013-01-08
+\clist_if_eq:NcT                                2013-01-08
+\clist_if_eq:NcTF                               2013-01-08
+\clist_length:c                                 2013-01-08
+\clist_length:N                                 2013-01-08
+\clist_length:n                                 2013-01-08
+\clist_remove_element:Nn                        2011-09-08
+\clist_top:cN                                   2011-09-08
+\clist_trim_spaces:c                            2011-12-20
+\clist_trim_spaces:N                            2011-12-20
+\clist_use:c                                    2013-01-08
+\clist_use:N                                    2013-01-08
+\cs_gnew_eq:cc                                  2011-09-08
+\cs_gnew_eq:cN                                  2011-09-08
+\cs_gnew_eq:Nc                                  2011-09-08
+\cs_gnew_nopar:cpn                              2011-09-08
+\cs_gnew_nopar:cpx                              2011-09-08
+\cs_gnew_nopar:Npn                              2011-09-08
+\cs_gnew_nopar:Npx                              2011-09-08
+\cs_gnew_protected_nopar:cpn                    2011-09-08
+\cs_gnew_protected_nopar:cpx                    2011-09-08
+\cs_gnew_protected_nopar:Npn                    2011-09-08
+\cs_gnew_protected_nopar:Npx                    2011-09-08
+\cs_gnew_protected:cpn                          2011-09-08
+\cs_gnew_protected:cpx                          2011-09-08
+\cs_gnew_protected:Npn                          2011-09-08
+\cs_gnew_protected:Npx                          2011-09-08
+\cs_gnew:cpn                                    2011-09-08
+\cs_gnew:cpx                                    2011-09-08
+\cs_gnew:Npn                                    2011-09-08
+\cs_gnew:Npx                                    2011-09-08
+\cs_gundefine:c                                 2011-09-08
+\cs_gundefine:N                                 2011-09-08
+\cs_set_eq:NwN                                  2011-12-30
+\dim_case:nnn                                   2015-07-14
+\dim_eval:w                                     2013-01-08
+\dim_eval_end:                                  2013-01-08
+\dim_gset_max:cn                                2013-01-08
+\dim_gset_max:Nn                                2013-01-08
+\dim_gset_min:cn                                2013-01-08
+\dim_gset_min:Nn                                2013-01-08
+\dim_set_max:cn                                 2013-01-08
+\dim_set_max:Nn                                 2013-01-08
+\dim_set_min:cn                                 2013-01-08
+\dim_set_min:Nn                                 2013-01-08
+\etex_....:D                                    2020-01-01
+\ExplSyntaxNamesOff                             2013-01-08
+\ExplSyntaxNamesOn                              2013-01-08
+\file_add_path:nN                               2018-12-27
+\file_if_exist_input:nT                         2018-03-05
+\file_if_exist_input:nTF                        2018-03-05
+\file_list:                                     2018-12-27
+\file_path_include:n                            2018-12-27
+\file_path_remove:n                             2018-12-27
+\fp_abs:c                                       2014-05-28
+\fp_abs:N                                       2014-05-28
+\fp_compare:NNNF                                2014-05-28
+\fp_compare:NNNT                                2014-05-28
+\fp_compare:NNNTF                               2014-05-28
+\fp_cos:cn                                      2014-05-28
+\fp_cos:Nn                                      2014-05-28
+\fp_div:cn                                      2014-05-28
+\fp_div:Nn                                      2014-05-28
+\fp_exp:cn                                      2014-05-28
+\fp_exp:Nn                                      2014-05-28
+\fp_gabs:c                                      2014-05-28
+\fp_gabs:N                                      2014-05-28
+\fp_gcos:cn                                     2014-05-28
+\fp_gcos:Nn                                     2014-05-28
+\fp_gdiv:cn                                     2014-05-28
+\fp_gdiv:Nn                                     2014-05-28
+\fp_gexp:cn                                     2014-05-28
+\fp_gexp:Nn                                     2014-05-28
+\fp_gln:cn                                      2014-05-28
+\fp_gln:Nn                                      2014-05-28
+\fp_gmul:cn                                     2014-05-28
+\fp_gmul:Nn                                     2014-05-28
+\fp_gneg:c                                      2014-05-28
+\fp_gneg:N                                      2014-05-28
+\fp_gpow:cn                                     2014-05-28
+\fp_gpow:Nn                                     2014-05-28
+\fp_ground_figures:cn                           2014-05-28
+\fp_ground_figures:Nn                           2014-05-28
+\fp_ground_places:cn                            2014-05-28
+\fp_ground_places:Nn                            2014-05-28
+\fp_gsin:cn                                     2014-05-28
+\fp_gsin:Nn                                     2014-05-28
+\fp_gtan:cn                                     2014-05-28
+\fp_gtan:Nn                                     2014-05-28
+\fp_if_undefined_p:N                            2014-05-28
+\fp_if_undefined:NF                             2014-05-28
+\fp_if_undefined:NT                             2014-05-28
+\fp_if_undefined:NTF                            2014-05-28
+\fp_if_zero_p:N                                 2014-05-28
+\fp_if_zero:NF                                  2014-05-28
+\fp_if_zero:NT                                  2014-05-28
+\fp_if_zero:NTF                                 2014-05-28
+\fp_ln:cn                                       2014-05-28
+\fp_ln:Nn                                       2014-05-28
+\fp_mul:cn                                      2014-05-28
+\fp_mul:Nn                                      2014-05-28
+\fp_neg:c                                       2014-05-28
+\fp_neg:N                                       2014-05-28
+\fp_pow:cn                                      2014-05-28
+\fp_pow:Nn                                      2014-05-28
+\fp_round_figures:cn                            2014-05-28
+\fp_round_figures:Nn                            2014-05-28
+\fp_round_places:cn                             2014-05-28
+\fp_round_places:Nn                             2014-05-28
+\fp_sin:cn                                      2014-05-28
+\fp_sin:Nn                                      2014-05-28
+\fp_tan:cn                                      2014-05-28
+\fp_tan:Nn                                      2014-05-28
+\g_file_current_name_tl                         2018-12-27
+\g_tmpa_toks                                    2011-09-08
+\g_tmpb_toks                                    2011-09-08
+\g_tmpc_toks                                    2011-09-08
+\group_execute_after:N                          2011-09-08
+\hbox_gset_inline_begin:c                       2014-08-09
+\hbox_gset_inline_begin:N                       2014-08-09
+\hbox_gset_inline_end:                          2014-08-09
+\hbox_set_inline_begin:c                        2014-08-09
+\hbox_set_inline_begin:N                        2014-08-09
+\hbox_set_inline_end:                           2014-08-09
+\hbox_unpack_clear:c                            2021-07-07
+\hbox_unpack_clear:N                            2021-07-07
+\if_num:w                                       2013-01-08
+\int_case:nnn                                   2015-07-14
+\int_convert_from_base_ten:nn                   2011-11-22
+\int_convert_from_symbols:nn                    2011-11-22
+\int_convert_to_base_ten:nn                     2011-11-22
+\int_eval:w                                     2013-01-08
+\int_eval_end:                                  2013-01-08
+\int_from_binary:n                              2016-01-05
+\int_from_hexadecimal:n                         2016-01-05
+\int_from_octal:n                               2016-01-05
+\int_to_binary:n                                2016-01-05
+\int_to_hexadecimal:n                           2016-01-05
+\int_to_octal:n                                 2016-01-05
+\int_to_symbol:n                                2011-11-22
+\int_value:w                                    2013-01-08
+\ior_get_str:NN                                 2018-03-05
+\ior_gto:NN                                     2013-07-28
+\ior_list_streams:                              2018-12-27
+\ior_log_streams:                               2018-12-27
+\ior_open_streams:                              2011-09-08
+\ior_str_gto:NN                                 2013-07-28
+\ior_str_to:NN                                  2013-07-28
+\ior_to:NN                                      2013-07-28
+\iow_list_streams:                              2018-12-27
+\iow_log_streams:                               2018-12-27
+\iow_now_buffer_safe:Nn                         2011-09-08
+\iow_now_buffer_safe:Nx                         2011-09-08
+\iow_now_when_avail:Nn                          2012-06-05
+\iow_now_when_avail:Nx                          2012-06-05
+\iow_open_streams:                              2011-09-08
+\iow_wrap:xnnnN                                 2013-01-08
+\KV_process_no_space_removal_no_sanitize:NNn    2011-09-08
+\KV_process_space_removal_no_sanitize:NNn       2011-09-08
+\KV_process_space_removal_sanitize:NNn          2011-09-08
+\l_iow_line_length_int                          2013-01-08
+\l_last_box                                     2012-05-11
+\l_tl_replace_toks                              2011-09-08
+\l_tmpa_toks                                    2011-09-08
+\l_tmpb_toks                                    2011-09-08
+\l_tmpc_int                                     2013-01-08
+\l_tmpc_toks                                    2011-09-08
+\lua_escape_x:n                                 2020-01-01
+\lua_now_x:n                                    2020-01-01
+\lua_shipout_x:n                                2020-01-01
+\luatex_...:D                                   2020-01-01
+\luatex_if_engine_p:                            2017-01-01
+\luatex_if_engine:F                             2017-01-01
+\luatex_if_engine:T                             2017-01-01
+\luatex_if_engine:TF                            2017-01-01
+\msg_class_new:nn                               2011-09-08
+\msg_class_set:nn                               2013-01-08
+\msg_direct_interrupt:xxxxx                     2011-09-08
+\msg_direct_log:xx                              2011-09-08
+\msg_direct_term:xx                             2011-09-08
+\msg_generic_new:nn                             2011-09-08
+\msg_generic_new:nnn                            2011-09-08
+\msg_generic_set:nn                             2011-09-08
+\msg_generic_set:nnn                            2011-09-08
+\msg_interrupt:nn                               2020-01-01
+\msg_interrupt:xxx                              2013-01-08
+\msg_log:n                                      2020-01-01
+\msg_log:x                                      2013-01-08
+\msg_newline:                                   2013-01-08
+\msg_term:n                                     2020-01-01
+\msg_term:x                                     2013-01-08
+\msg_trace:nn                                   2011-09-08
+\msg_trace:nnx                                  2011-09-08
+\msg_trace:nnxx                                 2011-09-08
+\msg_trace:nnxxx                                2011-09-08
+\msg_trace:nnxxxx                               2011-09-08
+\msg_two_newlines:                              2013-01-08
+\pdftex_...:D                                   2020-01-01
+\pdftex_if_engine_p:                            2017-01-01
+\pdftex_if_engine:F                             2017-01-01
+\pdftex_if_engine:T                             2017-01-01
+\pdftex_if_engine:TF                            2017-01-01
+\peek_after:NN                                  2011-09-08
+\peek_gafter:NN                                 2011-09-08
+\prg_case_dim:nnn                               2013-01-08
+\prg_case_int:nnn                               2013-01-08
+\prg_case_str:nnn                               2013-01-08
+\prg_case_str:onn                               2013-01-08
+\prg_case_str:xxn                               2013-01-08
+\prg_case_tl:cnn                                2013-01-08
+\prg_case_tl:Nnn                                2013-01-08
+\prg_new_map_functions:Nn                       2011-09-08
+\prg_set_map_functions:Nn                       2011-09-08
+\prg_stepwise_function:nnnN                     2013-01-08
+\prg_stepwise_inline:nnnn                       2013-01-08
+\prg_stepwise_variable:nnnNn                    2013-01-08
+\prop_del:cn                                    2013-01-08
+\prop_del:cV                                    2013-01-08
+\prop_del:Nn                                    2013-01-08
+\prop_del:NV                                    2013-01-08
+\prop_display:c                                 2011-09-08
+\prop_display:N                                 2011-09-08
+\prop_gdel:cn                                   2013-01-08
+\prop_gdel:cV                                   2013-01-08
+\prop_gdel:Nn                                   2013-01-08
+\prop_gdel:NV                                   2013-01-08
+\prop_get:cn                                    2016-01-05
+\prop_get:Nn                                    2016-01-05
+\prop_get_gdel:NnN                              2011-09-08
+\prop_gget:cnN                                  2011-09-08
+\prop_gget:cVN                                  2011-09-08
+\prop_gget:NnN                                  2011-09-08
+\prop_gget:NVN                                  2011-09-08
+\prop_gput:ccx                                  2011-09-08
+\prop_if_eq_p:cc                                2011-09-08
+\prop_if_eq_p:cN                                2011-09-08
+\prop_if_eq_p:Nc                                2011-09-08
+\prop_if_eq_p:NN                                2011-09-08
+\prop_if_eq:ccF                                 2011-09-08
+\prop_if_eq:ccT                                 2011-09-08
+\prop_if_eq:ccTF                                2011-09-08
+\prop_if_eq:cNF                                 2011-09-08
+\prop_if_eq:cNT                                 2011-09-08
+\prop_if_eq:cNTF                                2011-09-08
+\prop_if_eq:NcF                                 2011-09-08
+\prop_if_eq:NcT                                 2011-09-08
+\prop_if_eq:NcTF                                2011-09-08
+\prop_if_eq:NNF                                 2011-09-08
+\prop_if_eq:NNT                                 2011-09-08
+\prop_if_eq:NNTF                                2011-09-08
+\prop_if_in:ccF                                 2011-09-08
+\prop_if_in:ccT                                 2011-09-08
+\prop_if_in:ccTF                                2011-09-08
+\ptex_...:D                                     2020-01-01
+\quark_if_recursion_tail_break:N                2015-07-14
+\quark_if_recursion_tail_break:n                2015-07-14
+\scan_align_safe_stop:                          2017-01-01
+\seq_display:c                                  2011-09-08
+\seq_display:N                                  2011-09-08
+\seq_length:c                                   2013-01-08
+\seq_length:N                                   2013-01-08
+\seq_top:cN                                     2011-09-08
+\seq_top:NN                                     2011-09-08
+\seq_use:c                                      2013-01-08
+\seq_use:N                                      2013-01-08
+\skip_if_infinite_glue_p:n                      2013-01-08
+\skip_if_infinite_glue:nF                       2013-01-08
+\skip_if_infinite_glue:nT                       2013-01-08
+\skip_if_infinite_glue:nTF                      2013-01-08
+\sort_ordered:                                  2018-12-27
+\sort_reversed:                                 2018-12-27
+\str_case:nnn                                   2015-07-14
+\str_case:onn                                   2015-07-14
+\str_case_x:nn                                  2020-01-01
+\str_case_x:nnF                                 2020-01-01
+\str_case_x:nnn                                 2015-07-14
+\str_case_x:nnT                                 2020-01-01
+\str_case_x:nnTF                                2020-01-01
+\str_if_eq_p:xx                                 2013-01-08
+\str_if_eq_x:nnF                                2020-01-01
+\str_if_eq_x:nnT                                2020-01-01
+\str_if_eq_x:nnTF                               2020-01-01
+\str_if_eq_x_p:nn                               2020-01-01
+\str_if_eq:xxF                                  2013-01-08
+\str_if_eq:xxT                                  2013-01-08
+\str_if_eq:xxTF                                 2013-01-08
+\tl_case:cnn                                    2015-07-14
+\tl_case:Nnn                                    2015-07-14
+\tl_elt_count:c                                 2011-09-08
+\tl_elt_count:n                                 2011-09-08
+\tl_elt_count:N                                 2011-09-08
+\tl_elt_count:o                                 2011-09-08
+\tl_elt_count:V                                 2011-09-08
+\tl_gremove_all_in:cn                           2011-09-08
+\tl_gremove_all_in:Nn                           2011-09-08
+\tl_gremove_in:cn                               2011-09-08
+\tl_gremove_in:Nn                               2011-09-08
+\tl_greplace_all_in:cnn                         2011-09-08
+\tl_greplace_all_in:Nnn                         2011-09-08
+\tl_greplace_in:cnn                             2011-09-08
+\tl_greplace_in:Nnn                             2011-09-08
+\tl_gset:Nc                                     2011-09-08
+\tl_gset_from_file:cnn                          2021-07-07
+\tl_gset_from_file:Nnn                          2021-07-07
+\tl_gset_from_file_x:cnn                        2021-07-07
+\tl_gset_from_file_x:Nnn                        2021-07-07
+\tl_head_i:n                                    2011-09-08
+\tl_head_i:w                                    2011-09-08
+\tl_head_iii:f                                  2011-09-08
+\tl_head_iii:n                                  2011-09-08
+\tl_head_iii:w                                  2011-09-08
+\tl_if_empty:xF                                 2013-01-08
+\tl_if_empty:xT                                 2013-01-08
+\tl_if_empty:xTF                                2013-01-08
+\tl_if_head_group_p:n                           2013-01-08
+\tl_if_head_group:nF                            2013-01-08
+\tl_if_head_group:nT                            2013-01-08
+\tl_if_head_group:nTF                           2013-01-08
+\tl_if_head_N_type_p:n                          2013-01-08
+\tl_if_head_N_type:nF                           2013-01-08
+\tl_if_head_N_type:nT                           2013-01-08
+\tl_if_head_N_type:nTF                          2013-01-08
+\tl_if_head_space_p:n                           2013-01-08
+\tl_if_head_space:nF                            2013-01-08
+\tl_if_head_space:nT                            2013-01-08
+\tl_if_head_space:nTF                           2013-01-08
+\tl_length:c                                    2013-01-08
+\tl_length:n                                    2013-01-08
+\tl_length:N                                    2013-01-08
+\tl_length:o                                    2013-01-08
+\tl_length:V                                    2013-01-08
+\tl_new:cn                                      2011-09-08
+\tl_new:Nn                                      2011-09-08
+\tl_new:Nx                                      2011-09-08
+\tl_remove_all_in:cn                            2011-09-08
+\tl_remove_all_in:Nn                            2011-09-08
+\tl_remove_in:cn                                2011-09-08
+\tl_remove_in:Nn                                2011-09-08
+\tl_replace_all_in:cnn                          2011-09-08
+\tl_replace_all_in:Nnn                          2011-09-08
+\tl_replace_in:cnn                              2011-09-08
+\tl_replace_in:Nnn                              2011-09-08
+\tl_set:Nc                                      2011-09-08
+\tl_set_from_file:cnn                           2021-07-07
+\tl_set_from_file:Nnn                           2021-07-07
+\tl_set_from_file_x:cnn                         2021-07-07
+\tl_set_from_file_x:Nnn                         2021-07-07
+\tl_show_analysis:N                             2020-01-01
+\tl_show_analysis:n                             2020-01-01
+\tl_tail:w                                      2013-01-08
+\tl_to_lowercase:n                              2018-03-05
+\tl_to_uppercase:n                              2018-03-05
+\token_get_arg_spec:N                           2021-07-07
+\token_get_prefix_spec:N                        2021-07-07
+\token_get_replacement_spec:N                   2021-07-07
+\token_if_active_char_p:N                       2011-09-08
+\token_if_active_char:NF                        2011-09-08
+\token_if_active_char:NT                        2011-09-08
+\token_if_active_char:NTF                       2011-09-08
+\token_if_alignment_tab_p:N                     2011-09-08
+\token_if_alignment_tab:NF                      2011-09-08
+\token_if_alignment_tab:NT                      2011-09-08
+\token_if_alignment_tab:NTF                     2011-09-08
+\token_if_math_shift_p:N                        2011-09-08
+\token_if_math_shift:NF                         2011-09-08
+\token_if_math_shift:NT                         2011-09-08
+\token_if_math_shift:NTF                        2011-09-08
+\token_if_other_char_p:N                        2011-09-08
+\token_if_other_char:NF                         2011-09-08
+\token_if_other_char:NT                         2011-09-08
+\token_if_other_char:NTF                        2011-09-08
+\token_new:Nn                                   2018-12-29
+\toks_clear:c                                   2011-09-08
+\toks_clear:N                                   2011-09-08
+\toks_gclear:c                                  2011-09-08
+\toks_gclear:N                                  2011-09-08
+\toks_gput_left:cn                              2011-09-08
+\toks_gput_left:co                              2011-09-08
+\toks_gput_left:cV                              2011-09-08
+\toks_gput_left:Nn                              2011-09-08
+\toks_gput_left:No                              2011-09-08
+\toks_gput_left:NV                              2011-09-08
+\toks_gput_left:Nx                              2011-09-08
+\toks_gput_right:cn                             2011-09-08
+\toks_gput_right:co                             2011-09-08
+\toks_gput_right:cV                             2011-09-08
+\toks_gput_right:Nn                             2011-09-08
+\toks_gput_right:No                             2011-09-08
+\toks_gput_right:NV                             2011-09-08
+\toks_gput_right:Nx                             2011-09-08
+\toks_gset_eq:cc                                2011-09-08
+\toks_gset_eq:cN                                2011-09-08
+\toks_gset_eq:Nc                                2011-09-08
+\toks_gset_eq:NN                                2011-09-08
+\toks_gset:cn                                   2011-09-08
+\toks_gset:co                                   2011-09-08
+\toks_gset:cV                                   2011-09-08
+\toks_gset:cx                                   2011-09-08
+\toks_gset:Nn                                   2011-09-08
+\toks_gset:No                                   2011-09-08
+\toks_gset:NV                                   2011-09-08
+\toks_gset:Nx                                   2011-09-08
+\toks_if_empty_p:c                              2011-09-08
+\toks_if_empty_p:N                              2011-09-08
+\toks_if_empty:cF                               2011-09-08
+\toks_if_empty:cT                               2011-09-08
+\toks_if_empty:cTF                              2011-09-08
+\toks_if_empty:NF                               2011-09-08
+\toks_if_empty:NT                               2011-09-08
+\toks_if_empty:NTF                              2011-09-08
+\toks_if_eq_p:cc                                2011-09-08
+\toks_if_eq_p:cN                                2011-09-08
+\toks_if_eq_p:Nc                                2011-09-08
+\toks_if_eq_p:NN                                2011-09-08
+\toks_if_eq:ccF                                 2011-09-08
+\toks_if_eq:ccT                                 2011-09-08
+\toks_if_eq:ccTF                                2011-09-08
+\toks_if_eq:cNF                                 2011-09-08
+\toks_if_eq:cNT                                 2011-09-08
+\toks_if_eq:cNTF                                2011-09-08
+\toks_if_eq:NcF                                 2011-09-08
+\toks_if_eq:NcT                                 2011-09-08
+\toks_if_eq:NcTF                                2011-09-08
+\toks_if_eq:NNF                                 2011-09-08
+\toks_if_eq:NNT                                 2011-09-08
+\toks_if_eq:NNTF                                2011-09-08
+\toks_new:c                                     2011-09-08
+\toks_new:N                                     2011-09-08
+\toks_put_left:cn                               2011-09-08
+\toks_put_left:co                               2011-09-08
+\toks_put_left:cV                               2011-09-08
+\toks_put_left:Nn                               2011-09-08
+\toks_put_left:No                               2011-09-08
+\toks_put_left:NV                               2011-09-08
+\toks_put_left:Nx                               2011-09-08
+\toks_put_right:cn                              2011-09-08
+\toks_put_right:co                              2011-09-08
+\toks_put_right:cV                              2011-09-08
+\toks_put_right:Nf                              2011-09-08
+\toks_put_right:Nn                              2011-09-08
+\toks_put_right:No                              2011-09-08
+\toks_put_right:NV                              2011-09-08
+\toks_put_right:Nx                              2011-09-08
+\toks_set_eq:cc                                 2011-09-08
+\toks_set_eq:cN                                 2011-09-08
+\toks_set_eq:Nc                                 2011-09-08
+\toks_set_eq:NN                                 2011-09-08
+\toks_set:cf                                    2011-09-08
+\toks_set:cn                                    2011-09-08
+\toks_set:co                                    2011-09-08
+\toks_set:cV                                    2011-09-08
+\toks_set:cv                                    2011-09-08
+\toks_set:cx                                    2011-09-08
+\toks_set:Nf                                    2011-09-08
+\toks_set:Nn                                    2011-09-08
+\toks_set:No                                    2011-09-08
+\toks_set:NV                                    2011-09-08
+\toks_set:Nv                                    2011-09-08
+\toks_set:Nx                                    2011-09-08
+\toks_show:c                                    2011-09-08
+\toks_show:N                                    2011-09-08
+\toks_use_clear:c                               2011-09-08
+\toks_use_clear:N                               2011-09-08
+\toks_use_gclear:c                              2011-09-08
+\toks_use_gclear:N                              2011-09-08
+\toks_use:c                                     2011-09-08
+\toks_use:N                                     2011-09-08
+\uptex_...:D                                    2020-01-01
+\use_i_after_else:nw                            2011-12-30
+\use_i_after_fi:nw                              2011-12-30
+\use_i_after_or:nw                              2011-12-30
+\use_i_after_orelse:nw                          2011-12-30
+\utex_...:D                                     2020-01-01
+\vbox_gset_inline_begin:c                       2014-08-09
+\vbox_gset_inline_begin:N                       2014-08-09
+\vbox_gset_inline_end:                          2014-08-09
+\vbox_set_inline_begin:c                        2014-08-09
+\vbox_set_inline_begin:N                        2014-08-09
+\vbox_set_inline_end:                           2014-08-09
+\vbox_unpack_clear:c                            2021-07-07
+\vbox_unpack_clear:N                            2021-07-07
+\xetex_...:D                                    2020-01-01
+\xetex_if_engine_p:                             2017-01-01
+\xetex_if_engine:F                              2017-01-01
+\xetex_if_engine:T                              2017-01-01
+\xetex_if_engine:TF                             2017-01-01
+[fp function] round+                            2018-03-05
+[fp function] round-                            2018-03-05
+[fp function] round0                            2018-03-05
+[key property] .choice_code:n                   2015-07-14
+[key property] .choice_code:x                   2015-07-14
+[key property] .code:x                          2013-07-10
+[key property] .generate_choices:n              2015-07-14
+[key property] .meta:x                          2013-07-10
+[key property] .value_forbidden:                2017-01-01
+[key property] .value_required:                 2017-01-01
+Variants of n into N/c                          2018-12-27
+Variants of N into n/o/V/v/f/x                  2018-12-27
+Lua l3kernel table and functions therein        2022-01-06
+----------------------------------------------------------


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3obsolete.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.csv
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.csv	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.csv	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,296 @@
+Prefix,Module or package,Registrant,Homepage,Source repository,Issue tracker,First registered,Last update,Notes
+ENdiagram,endiagram,Clemens Niederberger,https://bitbucket.org/cgnieder/endiagram/,git@bitbucket.org:cgnieder/endiagram.git,https://bitbucket.org/cgnieder/endiagram/issues,2013-03-16,2013-03-16,
+GS,gs1,Markus Kohm,,,,2013-03-16,2013-03-16,
+MOdiagram,modiagram,Clemens Niederberger,https://bitbucket.org/cgnieder/modiagram/,git@bitbucket.org:cgnieder/modiagram.git,https://bitbucket.org/cgnieder/modiagram/issues,2013-03-16,2013-03-16,
+UFca,citeall,Ulrike Fischer,,,,2015-04-09,2016-02-26,
+acro,acro,Clemens Niederberger,https://github.com/cgnieder/acro/,https://github.com/cgnieder/acro.git,https://github.com/cgnieder/acro/issues,2013-03-16,2020-04-14,
+affiliations,langsci-affiliations,Felix Kopecky,https://ctan.org/pkg/langsci-affiliations,https://github.com/langsci/langsci-affiliations,https://github.com/langsci/langsci-affiliations/issues,2021-02-18,2021-02-18,
+akshar,akshar,Vu Van Dung,https://github.com/joulev/akshar,https://github.com/joulev/akshar.git,https://github.com/joulev/akshar/issues,2020-05-27,2020-05-27,
+algobox,algobox,Julien Rivaud,,,,2018-06-13,2018-06-13,
+alignment,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+alloc,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,Internal only but reserved
+ampersand,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+apfs,apfontspec,Qing Lee,https://github.com/CTeX-org/apfontspec,https://github.com/CTeX-org/apfontspec.git,https://github.com/CTeX-org/apfontspec/issues,2020-05-17,2020-05-17,
+arch,archaeologie,Lukas C. Bossert,http://www.biblatex-archaeologie.de,https://github.com/LukasCBossert/biblatex-archaeologie.git,https://github.com/LukasCBossert/biblatex-archaeologie/issues,2017-03-24,2017-03-24,
+array,hobby,Andrew Stacey,https://github.com/loopspace/hobby,https://github.com/loopspace/hobby,https://github.com/loopspace/hobby/issues,2013-03-16,2020-10-29,
+arsenal,arsenal,Boris Veytsman,https://github.com/borisveytsman/arsenal,https://github.com/borisveytsman/arsenal,https://github.com/borisveytsman/arsenal/issues,2023-09-04,2023-09-04,
+atsign,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+avm,langsci-avm,Felix Kopecky,https://ctan.org/pkg/langsci-avm,https://github.com/langsci/langsci-avm,https://github.com/langsci/langsci-avm/issues,2020-03-11,2020-03-11,
+babellatin,babel-latin,Keno Wehr,https://ctan.org/pkg/babel-latin,https://github.com/wehro/babel-latin,https://github.com/wehro/babel-latin/issues,2021-08-23,2021-08-23,
+backend,l3backend,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2019-06-04,2019-06-04,
+backslash,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+bearwear,bearwear,Ulrike Fischer,https://github.com/u-fischer/bearwear,https://github.com/u-fischer/bearwear,https://github.com/u-fischer/bearwear/issues,2020-04-24,2020-04-24,
+beuron,beuron,Keno Wehr,https://ctan.org/pkg/beuron,,,2021-08-23,2021-08-23,
+bitset,l3kernel,The LaTeX3 Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2020-12-26,2020-12-26,
+block,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2023-10-17,2023-10-17,
+bool,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+box,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+bxjh,BXjaholiday,Takuto Asakura,https://github.com/wtsnjp/BXjaholiday,https://github.com/wtsnjp/BXjaholiday.git,https://github.com/wtsnjp/BXjaholiday/issues,2018-02-02,2019-02-02,
+cascade,cascade,F. Pantigny,,,,2020-07-21,2020-07-21,
+catcode,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+cctab,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+cellprops,cellprops,Julien Rivaud,,,,2018-06-13,2018-06-13,
+chaos,"chaos,schleuderpackung",Marei Peischl,https://ds.ccc.de/,,,2021-05-28,2021-05-28,
+char,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+chemformula,chemformula,Clemens Niederberger,https://github.com/cgnieder/chemformula/,https://github.com/cgnieder/chemformula.git,https://github.com/cgnieder/chemformula/issues,2013-03-16,2020-04-14,
+chemmacros,chemmacros,Clemens Niederberger,https://github.com/cgnieder/chemmacros/,https://github.com/cgnieder/chemmacros.git,https://github.com/cgnieder/chemmacros/issues,2013-03-16,2020-04-14,
+chemnum,chemnum,Clemens Niederberger,https://github.com/cgnieder/chemnum/,https://github.com/cgnieder/chemnum.git,https://github.com/cgnieder/chemnum/issues,2013-03-16,2020-04-14,
+chk,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,Currently internal-only but reserved
+circumflex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+classics,classics,Eduardo C. Lourenço de Lima,,,,2013-03-16,2013-03-16,
+clist,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+cmd,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2021-01-20,2021-03-03,
+code,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-04-23,2021-04-23,
+codedesc,codedescribe,Alceu Frigeri,https://github.com/alceu-frigeri/codedescribe,https://github.com/alceu-frigeri/codedescribe,https://github.com/alceu-frigeri/codedescribe/issues,2023-05-15,2023-05-15,
+codedoc,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,Somewhat experimental: may change
+codehigh,codehigh,Jianrui Lyu,https://github.com/lvjr/codehigh,https://github.com/lvjr/codehigh.git,https://github.com/lvjr/codehigh/issues,2022-04-02,2022-04-02,
+codelist,codelisting,Alceu Frigeri,https://github.com/alceu-frigeri/codedescribe,https://github.com/alceu-frigeri/codedescribe,https://github.com/alceu-frigeri/codedescribe/issues,2023-05-15,2023-05-15,
+codepoint,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+coffin,"l3kernel,xcoffins",The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+colon,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+color,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+conteq,conteq,Joachim Breitner,https://github.com/nomeata/conteq,https://github.com/nomeata/conteq.git,https://github.com/nomeata/conteq/issues,2013-05-26,2013-05-27,
+cookingunits,cooking-units,Ben Vitecek,https://github.com/Vidabe/cooking-units,https://github.com/Vidabe/cooking-units.git,https://github.com/Vidabe/cooking-units/issues,2018-09-26,2018-09-26,
+cs,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+csl,citation-style-language,Zeping Lee,https://github.com/zepinglee/citeproc-lua,https://github.com/zepinglee/citeproc-lua.git,https://github.com/zepinglee/citeproc-lua/issues,2022-05-09,2022-05-09,
+csvsim,csvsimple,Thomas F. Sturm,https://github.com/T-F-S/csvsimple,https://github.com/T-F-S/csvsimple.git,https://github.com/T-F-S/csvsimple/issues,2020-02-19,2020-02-19,
+ctex,ctex,Qing Lee,https://github.com/CTeX-org/ctex-kit,https://github.com/CTeX-org/ctex-kit.git,https://github.com/CTeX-org/ctex-kit/issues,2014-03-08,2014-03-08,
+ctuthesis,ctuthesis,Tom Hejda,https://github.com/tohecz/ctuthesis,https://github.com/tohecz/ctuthesis.git,https://github.com/tohecz/ctuthesis/issues,2015-07-26,2015-07-26,
+debug,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2017-07-15,2017-07-15,
+denisbdoc,denisbdoc,Denis Bitouzé,https://github.com/dbitouze/denisbdoc,git@github.com:dbitouze/denisbdoc.git,,2020-05-13,2020-05-13,
+deriv,derivative,Simon Jensen,,,,2019-07-24,2019-07-24,
+didec,didec,Thomas F. Sturm,https://github.com/T-F-S/didec,https://github.com/T-F-S/didec.git,https://github.com/T-F-S/didec/issues,2024-02-02,2024-02-02,
+diffcoeff,diffcoeff,Andrew Parsloe,,,,2019-08-26,2019-08-26,
+dim,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+document,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2019-06-02,2019-06-02,
+dollar,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+driver,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+dry,dry,Michiel Helvensteijn,,,,2013-01-18,2013-01-18,
+ducksay,ducksay,Jonathan P. Spratte,https://github.com/Skillmon/ltx_ducksay,git@github.com:Skillmon/ltx_ducksay.git,https://github.com/Skillmon/ltx_ducksay/issues,2019-06-07,2019-06-07,
+duckuments,duckuments,Jonathan P. Spratte,https://github.com/Skillmon/ltx_duckuments,git@github.com:Skillmon/ltx_duckuments.git,https://github.com/Skillmon/ltx_duckuments/issues,2019-06-07,2019-06-07,
+e,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+else,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+emoji,emoji,Xiangdong Zeng,https://github.com/stone-zeng/latex-emoji,https://github.com/stone-zeng/latex-emoji.git,https://github.com/stone-zeng/latex-emoji/issues,2020-03-08,2020-03-08,
+emojicite,emojicite,Leon Sixt,https://github.com/berleon/emojicite,https://github.com/berleon/emojicite.git,https://github.com/berleon/emojicite/issues/,2020-04-14,2020-04-20,
+empty,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+enotez,enotez,Clemens Niederberger,https://github.com/cgnieder/enotez/,https://github.com/cgnieder/enotez.git,https://github.com/cgnieder/enotez/issues,2013-03-16,2020-04-14,
+etex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+etl,etl,Jonathan P. Spratte,https://github.com/Skillmon/ltx_etl,git@github.com:Skillmon/ltx_etl.git,https://github.com/Skillmon/ltx_etl/issues,2021-08-16,2021-08-16,
+exp,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+expl,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+exsheets,exsheets,Clemens Niederberger,https://bitbucket.org/cgnieder/exsheets/,git@bitbucket.org:cgnieder/exsheets.git,https://bitbucket.org/cgnieder/exsheets/issues,2013-03-16,2013-03-16,
+extblx,biblatex-ext,Moritz Wemheuer,https://github.com/moewew/biblatex-ext/,https://github.com/moewew/biblatex-ext.git,https://github.com/moewew/biblatex-ext/issues,2020-02-09,2020-02-09,
+exwf,exwrapfig,Takuto Asakura,https://github.com/wtsnjp/exwrapfig,https://github.com/wtsnjp/exwrapfig.git,https://github.com/wtsnjp/exwrapfig/issues,2018-06-07,2018-06-07,
+false,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-04-23,2021-04-23,
+fdu,fduthesis,Xiangdong Zeng,https://github.com/stone-zeng/fduthesis,https://github.com/stone-zeng/fduthesis.git,https://github.com/stone-zeng/fduthesis/issues,2018-06-14,2020-03-08,
+fdudoc,fduthesis,Xiangdong Zeng,https://github.com/stone-zeng/fduthesis,https://github.com/stone-zeng/fduthesis.git,https://github.com/stone-zeng/fduthesis/issues,2018-06-14,2020-03-08,
+fdulogo,fduthesis,Xiangdong Zeng,https://github.com/stone-zeng/fduthesis,https://github.com/stone-zeng/fduthesis.git,https://github.com/stone-zeng/fduthesis/issues,2018-06-14,2020-03-08,
+fi,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+file,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+filehook,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2020-10-01,2021-03-03,
+fingering,recorder-fingering,Alan Munn,https://github.com/amunn/recorder-fingering,https://github.com/amunn/recorder-fingering,https://github.com/amunn/recorder-fingering/issues,2023-02-17,2023-02-17,
+flag,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2017-02-13,
+fltr,newlfm,Paul Thomson,,,,2013-01-29,2013-01-29,
+fmdug,dashundergaps,Frank Mittelbach,https://www.latex-project.org/,https://github.com/FrankMittelbach/fmitex-dashundergaps.git,https://github.com/FrankMittelbach/fmitex-dashundergaps/issues,2018-06-24,2021-10-11,
+fmuft,unicodefonttable,Frank Mittelbach,https://www.latex-project.org/,https://github.com/FrankMittelbach/fmitex-unicodefonttable.git,https://github.com/FrankMittelbach/fmitex-unicodefonttable/issues,2020-02-17,2021-10-11,
+fmwao,widows-and-orphans,Frank Mittelbach,https://www.latex-project.org/,https://github.com/FrankMittelbach/fmitex-widows-and-orphans.git,https://github.com/FrankMittelbach/fmitex-widows-and-orphans/issues,2018-09-26,2018-09-26,
+fnote,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2023-10-17,2023-10-17,
+fnpct,fnpct,Clemens Niederberger,https://github.com/cgnieder/fnpct/,https://github.com/cgnieder/fnpct.git,https://github.com/cgnieder/fnpct/issues,2013-03-16,2020-04-14,
+fontsizes,fontsizes,Julien Rivaud,,,,,2018-06-13,
+fontspec,fontspec,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/fontspec.git,https://github.com/latex3/fontspec/issues,2013-03-16,2024-02-15,
+fp,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+fun,functional,Jianrui Lyu,https://github.com/lvjr/functional,https://github.com/lvjr/functional.git,https://github.com/lvjr/functional/issues,2022-04-02,2022-04-02,
+galley,l3galley,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+gatherenum,gatherenum,Julien Rivaud,,,,2018-06-13,2018-06-14,
+getree,genealogytree,Thomas F. Sturm,https://github.com/T-F-S/genealogytree,https://github.com/T-F-S/genealogytree.git,https://github.com/T-F-S/genealogytree/issues,2020-02-19,2020-02-19,
+ghsystem,ghsystem,Clemens Niederberger,https://github.com/cgnieder/ghsystem/,https://github.com/cgnieder/ghsystem.git,https://github.com/cgnieder/ghsystem/issues,2013-03-16,2020-04-14,
+graph,lt3graph,Michiel Helvensteijn,,,,2014-02-05,2014-02-05,
+group,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+gtl,gtl,Bruno Le Floch,https://github.com/blefloch/latex-gtl,https://github.com/blefloch/latex-gtl.git,https://github.com/blefloch/latex-gtl/issues,2015-09-22,2015-09-22,
+gzt,gzt,Denis Bitouzé,https://github.com/dbitouze/gzt,git@github.com:dbitouze/gzt.git,,2020-05-13,2020-05-13,
+hash,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+hbox,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+hcoffin,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+hobete,hobete,Tobias Görlach,http://www.disk0s1.de,,,2012-11-07,2012-11-07,
+hook,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2019-06-03,2021-03-03,
+hyp,hyperref,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/hyperref.git,https://github.com/latex3/hyperref/issues,2020-11-27,2020-11-27,
+if,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+incgra,incgraph,Thomas F. Sturm,https://github.com/T-F-S/incgraph,https://github.com/T-F-S/incgraph.git,https://github.com/T-F-S/incgraph/issues,2021-10-11,2021-10-11,
+inf,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+initex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-04-23,2021-04-23,
+insert,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+int,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+intarray,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-04-06,2018-04-06,
+ior,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+iot,iot,Island of TeX,https://islandoftex.gitlab.io,https://gitlab.com/islandoftex/texmf,https://gitlab.com/groups/islandoftex/texmf/-/issues,2023-07-18,2023-07-18,
+iow,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+iwonamath,iwonamath,Boris Veytsman,https://github.com/borisveytsman/iwonamath,https://github.com/borisveytsman/iwonamath,https://github.com/borisveytsman/iwonamath/issues,2023-09-04,2023-09-04,
+jiazhu,jiazhu,Qing Lee,https://github.com/CTeX-org/ctex-kit,https://github.com/CTeX-org/ctex-kit.git,https://github.com/CTeX-org/ctex-kit/issues,2020-05-17,2020-05-17,
+job,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-04-23,2021-04-23,
+kernel,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+keys,"l3kernel,l3keys2e,ltkeys",The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+keyval,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+kgl,kantlipsum,Enrico Gregorio,,,,2013-03-16,2013-03-16,
+kivitendo,"kiviletter, kivitables",Marei Peischl for Kivitendo,https://www.kivitendo.de/,https://github.com/kivitendo/kivitendo-erp,https://forum.kivitendo.de/,2021-05-28,2021-05-28,
+langsci,langscibook,Language Science Press,https://langsci-press.org,https://github.com/langsci/langscibook,https://github.com/langsci/langscibook/issues,2021-07-20,2021-07-21,
+left,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+lltxmath,lualatex-math,Philipp Stephani,https://github.com/phst/lualatex-math,https://github.com/phst/lualatex-math.git,https://github.com/phst/lualatex-math/issues,2012-11-07,2012-11-07,
+log,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+lua,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+luabridge,lt3luabridge,Vít Novotný,https://ctan.org/pkg/lt3luabridge,https://github.com/witiko/lt3luabridge.git,https://github.com/witiko/lt3luabridge/issues,2022-06-25,2022-06-25,
+luatex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+lwc,lua-widow-control,Max Chernoff,https://github.com/gucci-on-fleek/lua-widow-control,https://github.com/gucci-on-fleek/lua-widow-control.git,https://github.com/gucci-on-fleek/lua-widow-control/issues,2022-02-24,2022-02-24,
+mark,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+markdown,markdown,Vít Novotný,https://ctan.org/pkg/markdown,https://github.com/witiko/markdown.git,https://github.com/witiko/markdown/issues,2021-09-08,2021-09-08,
+marks,l3kernel/xmarks,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2020-02-17,2020-02-17,
+marks,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2021-03-03,2021-03-03,
+math,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+mathcolor,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2022-01-20,2022-01-20,
+max,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+mcrule,multicolrule,Karl Hagen,https://github.com/polysyllabic/multicolrule,https://github.com/polysyllabic/multicolrule.git,https://github.com/polysyllabic/multicolrule/issues,2018-12-24,2018-12-24,
+mermap,mercatormap,Thomas F. Sturm,https://github.com/T-F-S/mercatormap,https://github.com/T-F-S/mercatormap.git,https://github.com/T-F-S/mercatormap/issues,2020-02-19,2020-02-19,
+meta,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2022-01-20,2022-01-20,
+metrix,metrix,Tobias Weh,https://github.com/tweh/metrix,git@github.com:tweh/metrix.git,https://github.com/tweh/metrix/issues,2020-10-31,2019-10-09,
+mhchem,mhchem,Martin Hensel,,,,2014-02-05,2014-02-05,
+minibox,minibox,Will Robertson,,https://github.com/wspr/will2e.git,https://github.com/wspr/will2e/issues,2020-04-24,2020-04-24,
+minus,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+mix,media9,Alexander Grahn,,https://gitlab.com/agrahn/media9,https://gitlab.com/agrahn/media9/issues,2013-01-18,2020-04-15,
+mode,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+morewrites,morewrites,Bruno Le Floch,https://github.com/blefloch/latex-morewrites,https://github.com/blefloch/latex-morewrites.git,https://github.com/blefloch/latex-morewrites/issues,2013-03-16,2015-09-22,
+msg,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+msvg,media4svg,Alexander Grahn,,https://gitlab.com/agrahn/media4svg,https://gitlab.com/agrahn/media4svg/issues,2020-04-15,2020-04-15,
+muskip,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+namedef,namedef,Phelype Oleinik,https://github.com/PhelypeOleinik/namedef,https://github.com/PhelypeOleinik/namedef.git,https://github.com/PhelypeOleinik/namedef/issues,2020-06-22,2020-06-22,
+nan,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+nicematrix,nicematrix,François Pantigny,,,,2019-12-19,2019-12-19,
+nil,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+ninecolors,ninecolors,Jianrui Lyu,https://github.com/lvjr/ninecolors,https://github.com/lvjr/ninecolors.git,https://github.com/lvjr/ninecolors/issues,2022-04-02,2022-04-02,
+nmc,numerica,Andrew Parsloe,,,,2021-06-30,2021-06-30,
+no,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+notestobib,notes2bib,Joseph Wright,https://github.com/josephwright/notes2bib,https://github.com/josephwright/notes2bib.git,https://github.com/josephwright/notes2bib/issues,2012-11-07,2012-11-07,
+novalue,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+nwejm,nwejm,Denis Bitouzé,https://github.com/dbitouze/nwejm,git@github.com:dbitouze/nwejm.git,,2020-05-13,2020-05-13,
+ocgbase,ocgx2,Alexander Grahn,,https://gitlab.com/agrahn/ocgx2,https://gitlab.com/agrahn/ocgx2/issues,2016-02-26,2020-04-15,
+ocgxii,ocgx2,Alexander Grahn,,https://gitlab.com/agrahn/ocgx2,https://gitlab.com/agrahn/ocgx2/issues,2016-02-26,2020-04-15,
+one,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+or,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+other,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-04-23,2021-04-23,
+overleaf,overleaf,Overleaf,https://www.overleaf.com/about,,support+tex-dev@overleaf.com,2020-05-27,2020-05-27,
+para,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2021-03-03,2021-03-03,
+parameter,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+pbs,media9,Alexander Grahn,,https://gitlab.com/agrahn/media9,https://gitlab.com/agrahn/media9/issues,2016-02-26,2020-04-15,
+pdf,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2019-06-02,2019-06-02,
+pdfannot,l3pdfmanagement,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-02-23,2021-02-23,
+pdffile,l3pdfmanagement,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-02-23,2021-02-23,
+pdfmanagement,l3pdfmanagement,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2020-11-27,2020-11-27,
+pdfmeta,l3pdfmanagement,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-02-23,2021-02-23,
+pdfoverlay,pdfoverlay,David Purton,https://github.com/dcpurton/pdfoverlay,https://github.com/dcpurton/pdfoverlay.git,https://github.com/dcpurton/pdfoverlay/issues,2020-06-22,2020-06-22,
+pdftex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+pdfxform,l3pdfmanagement,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-02-23,2021-02-23,
+peek,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+percent,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+pgf,pgf,The PGF/TikZ Team,https://pgf-tikz.github.io,https://github.com/pgf-tikz/pgf,https://github.com/pgf-tikz/pgf/issues,2020-07-03,2020-07-03,
+pgfmxfp,pgfmath-xfp,Jonathan P. Spratte,https://github.com/Skillmon/ltx_pgfmath-xfp,https://github.com/Skillmon/ltx_pgfmath-xfp,https://github.com/Skillmon/ltx_pgfmath-xfp/issues,2021-05-20,2021-05-20,
+phone,phonenumbers,Keno Wehr,https://ctan.org/pkg/phonenumbers,https://github.com/wehro/phonenumbers,https://github.com/wehro/phonenumbers/issues,2021-08-23,2021-08-23,
+pi,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+piton,piton,François Pantigny,,,,29/09/2022,29/09/2022,
+pkgploader,pkgploader,Michiel Helvensteijn,,,,2014-02-05,2014-02-05,
+platex,platex,Japanese TeX Development Community,https://github.com/texjporg/platex,https://github.com/texjporg/platex.git,https://github.com/texjporg/platex/issues,2020-09-30,2020-09-30,
+polyglossia,polyglossia,Arthur Reutenauer,https://www.polyglossia.org/,https://github.com/reutenauer/polyglossia,https://github.com/reutenauer/polyglossia/issues,2019-09-03,,
+postnotes,postnotes,gusbrs,https://github.com/gusbrs/postnotes,https://github.com/gusbrs/postnotes.git,https://github.com/gusbrs/postnotes/issues,2022-04-23,2022-04-23,
+prelim,prelim2e,Marei Peischl,https://github.com/TeXhackse/prelim2e,https://github.com/TeXhackse/prelim2e.git,https://github.com/TeXhackse/prelim2e/issues,2020-11-24,2020-11-24,
+prg,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+primargs,morewrites,Bruno Le Floch,https://github.com/blefloch/latex-morewrites,https://github.com/blefloch/latex-morewrites.git,https://github.com/blefloch/latex-morewrites/issues,2013-03-16,2015-09-22,
+prop,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+property,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2021-01-20,2021-03-03,
+pseudo,pseudo,Magnus Lie Hetland,https://github.com/mlhetland/pseudo.sty,https://github.com/mlhetland/pseudo.sty.git,https://github.com/mlhetland/pseudo.sty/issues,2019-06-24,2019-06-24,
+ptex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2015-07-28,2015-07-28,
+ptxcd,ptxcd,Marei Peischl,,,,2020-07-27,2020-07-27,Used for specific corporate design templates
+qrbill,qrbill,Marei Peischl,https://github.com/peiTeX/qrbill,https://github.com/peiTeX/qrbill.git,https://github.com/peiTeX/qrbill/issues,2020-06-27,2020-06-27,
+quark,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+rainbow,beamertheme-rainbow,samcarter,https://github.com/samcarter/beamertheme-rainbow,https://github.com/samcarter/beamertheme-rainbow,https://github.com/samcarter/beamertheme-rainbow/issues,2023-07-04,2023-07-04,
+randomwalk,randomwalk,Bruno Le Floch,https://github.com/blefloch/latex-randomwalk,https://github.com/blefloch/latex-randomwalk.git,https://github.com/blefloch/latex-randomwalk/issues,2013-03-16,2015-09-22,
+rawobjects,rawobjects,Paolo De Donato,https://github.com/Loara/lt3rawobjects,https://github.com/Loara/lt3rawobjects/lt3rawobjects.git,https://github.com/Loara/lt3rawobjects/issues,2022-07-19,2022-07-19,
+recursion,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+ref,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2020-12-24,2020-12-24,
+regex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2018-04-06,
+reverse,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+right,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+rivbook,rivbook,Julien Rivaud,,,,2018-06-13,2018-06-14,
+rivmath,rivmath,Julien Rivaud,,,,2018-06-13,2018-06-13,
+sanuml,sanitize-umlaut,Thomas F. Sturm,https://github.com/T-F-S/sanitize-umlaut,https://github.com/T-F-S/sanitize-umlaut.git,https://github.com/T-F-S/sanitize-umlaut/issues,2022-07-19,2022-07-19,
+scan,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+schulma,schulmathematik,Keno Wehr,https://ctan.org/pkg/schulmathematik,,,2021-08-23,2021-08-23,
+scontents,scontents,Pablo González,https://github.com/pablgonz/scontents,git@github.com:pablgonz/scontents.git,https://github.com/pablgonz/scontents/issues,2019-12-05,2019-12-05,
+scripture,scripture,David Purton,https://github.com/dcpurton/scripture,https://github.com/dcpurton/scripture.git,https://github.com/dcpurton/scripture/issues,2022-07-27,2022-07-27,
+sdaps,sdaps,Benjamin Berg,https://sdaps.org,https://github.com/sdaps/sdaps-class.git,https://github.com/sdaps/sdaps-class/issues,2020-02-17,2020-02-17,
+seq,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+shipout,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2020-10-01,2021-03-03,
+silly,sillypage,Paulo Cereda,https://github.com/cereda/sillypage,https://github.com/cereda/sillypage.git,https://github.com/cereda/sillypage/issues,2022-02-01,2022-02-01,
+siunitx,siunitx,Joseph Wright,https://github.com/josephwright/siunitx,https://github.com/josephwright/siunitx.git,https://github.com/josephwright/siunitx/issues,2012-11-04,2012-11-04,
+skel,skeldoc,Magnus Lie Hetland,https://github.com/mlhetland/skeldoc.sty,https://github.com/mlhetland/skeldoc.sty.git,https://github.com/mlhetland/skeldoc.sty/issues,2021-01-04,2021-01-04,
+skip,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+slcd,se2thesis,Stephan Lukasczyk,https://github.com/se2p/se2thesis,https://github.com/se2p/se2thesis,https://github.com/se2p/se2thesis/issues,2023-10-18,2023-10-18,
+socket,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2023-10-17,2023-10-17,
+sort,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2017-02-13,
+space,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+starray,starray,Alceu Frigeri,https://github.com/alceu-frigeri/starray,https://github.com/alceu-frigeri/starray,https://github.com/alceu-frigeri/starray/issues,2023-05-15,2023-05-15,
+statistics,statistics,Julien Rivaud,https://gitlab.com/frnchfrgg-latex/statistics,https://gitlab.com/frnchfrgg-latex/statistics.git,https://gitlab.com/frnchfrgg-latex/statistics/issues,2018-06-25,2018-06-25,
+stm,lt3-stm,CV Radhakrishnan,http://www.cvr.cc/,,,2014-02-26,2014-02-26,
+stop,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+str,"l3kernel,l3str-format",The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+stycmd,styledcmd,Paolo De Donato,https://github.com/Loara/styledcmd,https://github.com/Loara/styledcmd.git,https://github.com/Loara/styledcmd/issues,2021-08-30,2021-08-30,
+substances,substances,Clemens Niederberger,https://github.com/cgnieder/substances/,https://github.com/cgnieder/substances.git,https://github.com/cgnieder/substances/issues,2013-03-16,2020-04-14,
+sys,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2015-09-07,2015-09-08,
+tag,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2019-06-02,2019-06-02,
+tasks,tasks,Clemens Niederberger,https://github.com/cgnieder/tasks/,https://github.com/cgnieder/tasks.git,https://github.com/cgnieder/cgnieder/tasks/issues,2013-03-16,2020-04-14,
+tbl,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2023-10-23,2023-10-23,
+tblr,tabularray,Jianrui Lyu,https://github.com/lvjr/tabularray,https://github.com/lvjr/tabularray.git,https://github.com/lvjr/tabularray/issues,2022-04-02,2022-04-02,
+tcobox,tcolorbox,Thomas F. Sturm,https://github.com/T-F-S/tcolorbox,https://github.com/T-F-S/tcolorbox.git,https://github.com/T-F-S/tcolorbox/issues,2020-02-19,2020-02-19,
+template,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2021-01-20,2021-03-03,
+term,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+tex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+text,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2020-01-15,2020-01-15,
+tikzfill,tikzfill,Thomas F. Sturm,https://github.com/T-F-S/tikzfill,https://github.com/T-F-S/tikzfill.git,https://github.com/T-F-S/tikzfill/issues,2022-07-19,2022-07-19,
+tikzlings,tikzlings,samcarter,https://github.com/samcarter/tikzlings,git@github.com:samcarter/tikzlings.git,https://github.com/samcarter/tikzlings/issues,2023-02-17,2023-02-17,
+tikzsymbols,tikzsymbols,Ben Vitecek,https://github.com/Vidabe/tikzsymbols,https://github.com/Vidabe/tikzsymbols.git,https://github.com/Vidabe/tikzsymbols/issues,2018-09-26,2018-09-26,
+tilde,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+tl,"l3kernel,l3tl-build",The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+tmpa,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+tmpb,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+token,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+true,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-04-23,2021-04-23,
+twmk,menukeys,Tobias Weh,https://github.com/tweh/menukeys,git@github.com:tweh/menukeys.git,https://github.com/tweh/menukeys/issues,2020-10-31,2020-10-31,“classic” L2 package using only some expl3 code
+ufcombo,combofont,Ulrike Fischer,https://github.com/u-fischer/combofont,https://github.com/u-fischer/combofont,https://github.com/u-fischer/combofont/issues,2020-04-24,2020-04-24,
+ufgrid,returntogrid,Ulrike Fischer,https://github.com/u-fischer/returntogrid,https://github.com/u-fischer/returntogrid,https://github.com/u-fischer/returntogrid/issues,2020-04-24,2020-04-24,
+uftag,tagpdf,Ulrike Fischer,,,,2018-07-15,2018-07-15,
+um,unicode-math,Will Robertson,https://github.com/wspr/unicode-math,https://github.com/wspr/unicode-math.git,https://github.com/wspr/unicode-math/issues,2013-03-16,2013-03-16,
+underscore,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+unravel,unravel,Bruno Le Floch,https://github.com/blefloch/latex-unravel,https://github.com/blefloch/latex-unravel.git,https://github.com/blefloch/latex-unravel/issues,2015-09-22,2015-09-22,
+uptex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2015-07-28,2015-07-28,
+use,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+utex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2015-07-28,2015-07-28,
+vbox,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+vcoffin,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+wheelchart,wheelchart,Matthias Floré,,,,2023-12-07,2023-12-07,
+withargs,withargs,Michiel Helvensteijn,,,,2014-02-05,2014-02-05,
+witharrows,witharrows,François Pantigny,,,,2019-12-19,2019-12-19,
+xeCJK,xecjk,Qing Lee,https://github.com/CTeX-org/ctex-kit,https://github.com/CTeX-org/ctex-kit.git,https://github.com/CTeX-org/ctex-kit/issues,2013-05-26,2013-05-26,
+xetex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+xfrac,xfrac,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/xfrac.git,https://github.com/latex3/xfrac/issues,2012-09-27,2024-02-14,
+xmarks,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2021-03-03,2021-03-03,
+xparse,xparse,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+xpatch,"regexpatch,xpatch",Enrico Gregorio,,,,2013-03-16,2013-03-16,
+xpeek,xpeek,Joel C. Salomon,,,,2013-03-16,2013-03-16,
+xpinyin,xpinyin,Qing Lee,https://github.com/CTeX-org/ctex-kit,https://github.com/CTeX-org/ctex-kit.git,https://github.com/CTeX-org/ctex-kit/issues,2013-03-16,2013-05-26,
+xsb,xsavebox,Alexander Grahn,,https://gitlab.com/agrahn/xsavebox,https://gitlab.com/agrahn/xsavebox/issues,2016-02-26,2020-04-15,
+xsim,xsim,Clemens Niederberger,https://github.com/cgnieder/xsim/,https://github.com/cgnieder/xsim.git,https://github.com/cgnieder/xsim/issues,2020-04-14,2020-04-14,
+xtemplate,xtemplate,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+yoin,yoin,Tom Hejda,https://github.com/tohecz/yoin,https://github.com/tohecz/yoin.git,https://github.com/tohecz/yoin/issues,2016-02-22,2016-02-22,
+zero,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
+zhlipsum,zhlipsum,Xiangdong Zeng,https://github.com/stone-zeng/zhlipsum,https://github.com/stone-zeng/zhlipsum.git,https://github.com/stone-zeng/zhlipsum/issues,2018-06-14,2018-06-14,
+zhnum,zhnumber,Qing Lee,https://github.com/CTeX-org/ctex-kit,https://github.com/CTeX-org/ctex-kit.git,https://github.com/CTeX-org/ctex-kit/issues,2013-03-16,2013-05-26,
+zrefcheck,zref-check,gusbrs,https://github.com/gusbrs/zref-check,https://github.com/gusbrs/zref-check,https://github.com/gusbrs/zref-check/issues,2021-08-05,2021-08-05,
+zrefclever,zref-clever,gusbrs,https://github.com/gusbrs/zref-clever,https://github.com/gusbrs/zref-clever,https://github.com/gusbrs/zref-clever/issues,2021-11-29,2021-11-29,
+zrefvario,zref-vario,gusbrs,https://github.com/gusbrs/zref-vario,https://github.com/gusbrs/zref-vario,https://github.com/gusbrs/zref-vario/issues,2022-02-02,2022-02-02,
+zxjt,zxjatype,Takayuki Yato,,,,2013-03-16,2013-03-16,


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.csv
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,91 @@
+\iffalse meta-comment
+
+File:l3prefixes.tex
+
+Copyright (C) 2019,2021 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 released version of this bundle is available from CTAN.
+
+-----------------------------------------------------------------------
+
+The development version of the bundle can be found at
+
+   https://github.com/latex3/latex3
+
+for those people who are interested.
+
+\fi
+
+\documentclass{article}
+\usepackage{expl3}
+\usepackage{array}
+\usepackage{booktabs}
+\usepackage{longtable}
+\ExplSyntaxOn
+\cs_new_protected:Npn \__prefix_readi:w #1 " #2 " #3 \q_stop
+  {
+    \quark_if_nil:nTF {#2}
+      { \__prefix_readii:w #1 \q_stop }
+      { \__prefix_readi:w #1 {#2} #3 \q_stop }
+  }
+\cs_new_protected:Npn \__prefix_readii:w #1 , #2 , #3 , #4 \q_stop
+  { \__prefix_readiii:nnw {#1} {#3} #2 , \q_stop }
+\cs_new_protected:Npn \__prefix_readiii:nnw #1 #2 #3 , #4 \q_stop
+  {
+    \tl_put_right:Nn \l_tmpb_tl { #1 & #3 & #2 \\ }
+    \tl_if_blank:nF {#4}
+      { \clist_map_inline:nn {#4} { \tl_put_right:Nn \l_tmpb_tl { & ##1 \\ } } }
+  }
+\ior_new:N \l_tmpa_ior
+\ior_open:Nn \l_tmpa_ior { l3prefixes.csv }
+\ior_get:NN \l_tmpa_ior \l_tmpa_tl % Throw away
+\cs_new_protected:Npn \PrintTable
+  {
+    \tl_set:Nn \l_tmpb_tl
+      {
+        \begin { longtable } { @{} *{2}{>{\ttfamily}l} l @{} }
+        \toprule
+          \multicolumn{1}{@{}l}{Prefix}
+          & \multicolumn{1}{l@{}}{Module}
+          & Registrant \\
+        \midrule
+        \endhead
+        \bottomrule
+        \endfoot
+      }
+    \ior_map_inline:Nn \l_tmpa_ior
+      { \__prefix_readi:w ##1 " \q_nil " \q_stop }
+    \tl_put_right:Nn \l_tmpb_tl { \end { longtable } }
+    \tl_replace_all:Nnn \l_tmpb_tl { LaTeX3 } { \LaTeX3 }
+    \tl_use:N \l_tmpb_tl
+  }
+\ExplSyntaxOff
+\begin{document}
+
+This file lists the prefixes which have been registered with the \LaTeX{}
+team for use in \textsf{expl3} code. Programmers are invited to register their
+(public) prefix use by contacting the team at
+\begin{quote}
+  \texttt{modules at latex-project.org}
+\end{quote}
+with the relevant information for the \texttt{.csv} file, i.e.,
+\textit{Prefix, Module or package, Registrant, Homepage, Source repository, Issue tracker}.
+
+
+We recommend that short prefixes are avoided as there are a limited
+number of these very general names available.  The
+file \texttt{l3prefixes.csv} contains more details on each module, for
+example any information on source repository or issue tracker.
+
+\PrintTable
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3prefixes.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,303 @@
+\iffalse meta-comment
+
+File: l3styleguide.tex
+
+Copyright (C) 2011,2012,2014-2024 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 released version of this bundle is available from CTAN.
+
+\fi
+
+\documentclass{l3doc}
+
+
+\title{%
+  The \LaTeX3 kernel: style guide for code authors%
+}
+\author{%
+  The \LaTeX{} Project\thanks
+    {%
+      E-mail:
+      \href{mailto:latex-team at latex-project.org}%
+        {latex-team at latex-project.org}%
+    }%
+}
+\date{Released 2024-04-11}
+
+\begin{document}
+
+\maketitle
+
+\tableofcontents
+
+\section{Introduction}
+
+This document is intended as a style guide for authors of code and
+documentation for the \LaTeX3 kernel. It covers both aspects of coding
+style and the formatting of the sources. The aim of providing these
+guidelines is help ensure consistency of the code and sources from
+different authors. Experience suggests that in the long-term this helps
+with maintenance. There will of course be places where there are
+exceptions to these guidelines: common sense should always be
+applied!
+
+\section{Documentation style}
+
+\LaTeX3 source and documentation should be written using the document
+class \cls{l3doc} in \file{dtx} format. This class provides a number
+of logical mark up elements, which should be used where possible.
+In the main, this is standard \LaTeX{} practice, but there are a
+few points to highlight:
+\begin{itemize}
+  \item
+    Where possible, use \cs{cs} to mark up control sequences
+    rather than using a verbatim environment.
+  \item
+    Arguments which are given in braces should be marked using
+    \cs{Arg} when code-level functions are discussed, but using
+    \cs{marg} for document functions.
+  \item
+    The names \TeX{}, \LaTeX{}, \emph{etc}.\ use the normal logical mark
+    up followed by an empty group (|{}|), with the exception of |\LaTeX3|,
+    where the number should follow directly.
+  \item
+    Where in line verbatim text is used, it should be marked up
+    using the \verb=|...|= construct (\emph{i.e.}~vertical bars delimit
+    the verbatim text).
+  \item In line quotes should be marked up using the \cs{enquote}
+    function.
+  \item
+    Where numbers in the source have a mathematical meaning,
+    they should be included in math mode. Such in-line math mode
+    material should be marked up using |$...$| and  \emph{not}
+    |\(...\)|.
+\end{itemize}
+
+Line length in the source files should be under $80$
+characters where possible, as this helps keep everything on the screen
+when editing files. In the \file{dtx} format, documentation lines start
+with a \texttt{\%}, which is usually followed by a space to leave a
+\enquote{comment margin} at the start of each line.
+
+As with code indenting (see later), nested environments and arguments
+should be indented by (at least) two spaces to make the nature of the nesting
+clear. Thus for example a typical arrangement for the \env{function}
+environment might be
+\begin{verbatim*}
+\begin{function}{\seq_gclear:N, \seq_gclear:c}
+  \begin{syntax}
+    \cs{seq_gclear:N} \meta{sequence}
+  \end{syntax}
+  Clears all entries from the \meta{sequence} globally.
+\end{function}
+\end{verbatim*}
+The \enquote{outer} \verb*|% \begin{function}| should have the customary
+space after the |%| character at the start of the line.
+
+In general, a single \env{function}  or \env{macro} environment should be
+used for a group of closely-related functions, for example argument
+specification variants. In such cases, a comma-separated list should be
+used, as shown in the preceding example.
+
+\section{Format of the code itself}
+
+The requirement for fewer than $80$ characters per line applies to the code
+itself as well as the surrounding documentation. A number of the general
+style principles for \LaTeX3 code apply: these are described in the following
+paragraph and an example is then given.
+
+With the exception of simple runs of parameter (|{#1}|, |#1#2|,
+\emph{etc.}), everything should be divided up using spaces to make the code
+more readable. In general, these will be single spaces, but in some
+places it makes more sense to align parts of the code to emphasise
+similarity. (Tabs should not be used for introducing white space.)
+
+Each conceptually-separate step in a function should be on a separate
+line, to make the meaning clearer. Hence the \texttt{false} branch
+in the example uses two lines for the two auxiliary function uses.
+
+Within the definition, a two-space indent should be used to show each
+\enquote{level} of code. Thus in the example \cs{tl_if_empty:nTF} is
+indented by two spaces, but the two branches are indented by four
+spaces. Within the \texttt{false} branch, the need for multiple lines
+means that an additional two-space indent should be used to show that
+these lines are all part of the brace group.
+
+The result of these lay-out conventions is code which in general
+looks like the example:
+\begin{verbatim*}
+\cs_new:Npn \module_foo:nn #1#2
+  {
+    \tl_if_empty:nTF {#1}
+      { \module_foo_aux:n { X #2 } }
+      {
+        \module_foo_aux:nn {#1} {#2}
+        \module_foo_aux:n { #1 #2 }
+      }
+  }
+\end{verbatim*}
+
+\section{Code conventions}
+
+All code-level functions should be \enquote{long} if they accept any
+arguments, even if it seems \enquote{very unlikely} that a \cs{par} token
+will be passed. Thus \cs{cs_new_nopar:Npn} and so forth should only be used
+to create interfaces at the document level (where trapping \cs{par} tokens
+may be appropriate) or where comparison to other code known not to be
+\enquote{long} is required (\emph{e.g.}~when working with mixed
+\LaTeXe{}/\pkg{expl3} situations).
+
+The expandability of each function should be well-defined. Functions which
+cannot be fully expanded must be \texttt{protected}. This means that expandable
+functions must themselves only contain expandable material. Functions which
+use any non-expandable material must be defined using \cs{cs_new_protected:Npn}
+or similar.
+
+When using \cs{cs_generate_variant:Nn}, group related variants together
+to make the pattern clearer. A common example is variants of a function
+which has an \texttt{N}-type first argument:
+\begin{verbatim}
+  \cs_generate_variant:Nn \foo:Nn {     NV , No }
+  \cs_generate_variant:Nn \foo:Nn { c , cV , co }
+\end{verbatim}
+
+There may be cases where omitting braces from \texttt{o}-type arguments
+is desirable for performance reasons. This should only be done if the
+argument is a single token, thus for example
+\begin{verbatim}
+  \tl_set:No \l_some_tl \l_some_other_tl
+\end{verbatim}
+remains clear and can be used where appropriate.
+
+\section{Private and internal functions}
+
+Private functions (those starting \cs{__}) should not be used between modules.
+The only exception is where a \enquote{family} of modules share some
+\enquote{internal} methods: this happens most obviously in the kernel itself.
+Any internal functions or variables \emph{must} be documented in the same way
+as public ones.
+
+The \pkg{DocStrip} method should be used for internal functions in a module.
+This requires a line
+\begin{quote}
+  \ttfamily
+  \%<@@=\meta{module}>
+\end{quote}
+at the start of the source (\texttt{.dtx}) file, with internal functions
+then written in the form
+\begin{verbatim}
+  \cs_new_protected:Npn \@@_function:nn #1#2
+    ...
+\end{verbatim}
+
+\subsection{Access from other modules}
+
+There may be cases where it is useful to use an internal function from
+a third-party module (this includes cases where you are the author of both
+but they are not part of the same \enquote{family}). In these cases, you should
+\emph{copy} the definition of the internal function to your code: this avoids
+relying on non-documented interfaces. At the same time, it is strongly
+encouraged that you discuss your requirements with the author of the
+code you need to access. The best long-term solution to these cases is for
+new documented interfaces to be added to the parent module.
+
+\subsection{Access to primitives}
+
+As \pkg{expl3} is still a developing system, there are places where direct
+access to engine primitives is required. These are all marked as
+\enquote{do not use} in the code and so require special handling. Where a
+programmer is sure that they need to use a primitive (for example where the
+team have not yet covered access to an area) then a local copy of the
+primitive should be made, for example
+\begin{verbatim}
+  \cs_new_eq:NN \__module_message:w \tex_message:D
+  % ...
+  \cs_new_protected:Npn \__module_fancy_msg:n #1
+    { \__module_message:w { *** #1 *** } }
+\end{verbatim}
+This approach makes it possible for the team and others to find such
+usage (by searching for the \texttt{:D} argument type) but avoids
+multiple uses in general code.
+
+At the same time, the team ask that these use cases are raised on the
+\texttt{LaTeX-L} mailing list. The team are keen to collect use cases for
+areas that have not yet been addressed and to provide new code where the
+required interfaces become clear.
+
+Programmers using primitives should be ready to make updates to their
+code as the team develop additional interfaces.
+
+\section{Auxiliary functions}
+
+In general, the team encourages the use of descriptive names in \LaTeX3 code.
+Thus many helper functions would have names which describe briefly what they do,
+rather than simply indicating that they are auxiliary to some higher-level
+function. However, there are places where one or more \texttt{aux} functions
+are required. Where possible, these should be differentiated by signature
+\begin{verbatim}
+  \cs_new_protected:Npn \@@_function:nn #1#2
+    {
+      ...
+    }
+  \cs_new_protected:Npn \@@_function_aux:nn #1#2
+    {
+      ...
+    }
+  \cs_new_protected:Npn \@@_function_aux:w #1#2 \q_stop
+    {
+      ...
+    }
+\end{verbatim}
+Where more than one auxiliary shares the same signature, the recommended naming
+scheme is \texttt{auxi}, \texttt{auxii} and so on.
+\begin{verbatim}
+  \cs_new_protected:Npn \@@_function_auxi:nn #1#2
+    {
+      ...
+    }
+  \cs_new_protected:Npn \@@_function_auxii:nn #1#2
+    {
+      ...
+    }
+\end{verbatim}
+The use of \texttt{aux_i}, \texttt{aux_ii}, \emph{etc.}\ is discouraged as this
+conflicts with the convention used by \cs{use_i:nn} and related functions.
+
+\section{Functions with `weird' arguments}
+
+When defining commands that do not follow the usual convention of accepting
+arguments as single-tokens or braced-text, the \verb|w| argument specifier
+is used to denote that the function signature cannot fully describe the syntax.
+Two examples from the \LaTeX3 kernel are:
+\begin{quote}
+\verb|\use_none_delimit_by_q_stop:w| $\langle$\,\emph{text}\,$\rangle$ \verb|\q_stop|\\
+\verb|\use_i_delimit_by_q_stop:nw| \char`\{ $\langle$\,\emph{arg}\,$\rangle$\char`}\,$\langle$\,\emph{text}\,$\rangle$ \verb|\q_stop|
+\end{quote}
+More complex definitions are possible if commands are to parse tokens,
+such as the internal kernel command
+\begin{verbatim}
+    \cs_new_protected:Npn \__clist_get:wN #1 , #2 \q_stop #3
+      { \tl_set:Nn #3 {#1} }
+\end{verbatim}
+When the \verb|w| specifier is being used, it is encouraged not to try
+and complicate the rest of the signature too much---for example, it
+would be considered poor style to have a function with a signature like
+\verb|\foo_bar:wnw| unless there were very clear reasons of code clarity.
+A signature such as \verb|:ww| would certainly be discouraged.
+
+Examining the examples above, it can be seen that there are scenarios in
+which it may make logical sense for having a signature such as \verb|:wN| or
+\verb|:nw|, but when in doubt the recommended approach is to simply use
+\verb|:w| as a catch-all.
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3styleguide.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,190 @@
+\iffalse meta-comment
+
+File: l3syntax-changes.tex
+
+Copyright (C) 2011,2012,2017-2024 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 released version of this bundle is available from CTAN.
+
+\fi
+
+\documentclass{l3doc}
+
+
+\title{%
+  Syntax changes in \LaTeX3 functions%
+}
+\author{%
+  The \LaTeX{} Project\thanks
+    {%
+      E-mail:
+      \href{mailto:latex-team at latex-project.org}%
+        {latex-team at latex-project.org}%
+    }%
+}
+\date{Released 2024-04-11}
+
+\newcommand{\TF}{\textit{(TF)}}
+
+\begin{document}
+
+\maketitle
+
+This file describes functions that were expected to be completely
+stable, but whose syntax has changed in ways that may potentially
+require code relying on them to be changed.  This file does not include
+bug-fixes, nor backward-compatible extensions of the syntax,
+nor functions that were completely
+deprecated: the latter are listed in \texttt{l3obsolete.txt}.  Only
+changes after August 2011 are listed, with an approximate date.
+
+\section{August 2011}
+
+\begin{itemize}
+  \item \cs{tl_if_single:n\TF} recognized any non-zero number of
+    explicit spaces as \meta{true}, and did not ignore trailing spaces.
+    Now it is \meta{true} for
+    \[
+      \meta{optional spaces}
+      \meta{normal token or brace group}
+      \meta{optional spaces}.
+    \]
+  \item \cs{tl_reverse:n} stripped outer braces and lost unprotected spaces.
+    Now it keeps spaces, leaves unbraced single tokens unbraced, and
+    braced groups braced.
+  \item \cs{tl_trim_spaces:n} only removed one leading and trailing space.
+    Now removes recursively. Also, on the left it used to strip implicit
+    and explicit spaces with any character code. Now it strips only explicit
+    space characters $(32,10)$.
+\end{itemize}
+
+\section{September 2011}
+
+\begin{itemize}
+\item clist functions which receive an \texttt{n}-type comma list argument
+  now trim spaces from each item in the argument.
+\end{itemize}
+
+\section{May 2012}
+
+\begin{itemize}
+  \item The \pkg{l3fp} code has been completely rewritten with a new
+    expandable interface.
+  \item Getting/popping from a comma list or sequence or property list
+    that is empty (or missing the given key) now gives the quark
+    \cs{q_no_value}.
+\end{itemize}
+
+\section{June 2012}
+
+\begin{itemize}
+  \item Access to list functions now indexes from~$1$, not from~$0$.
+  This applies to multiple choices in the \pkg{l3keys} module and
+  the \cs{clist_item:Nn}, \cs{seq_item:Nn} and \cs{tl_item:Nn}
+  functions.
+  \item \cs{tl_trim_spaces:n} now requires a variable number of
+  expansions to fully expand, rather than exactly two.  Of course,
+  \texttt{x}-type or \texttt{e}-type expansion still correctly evaluates this function.
+\end{itemize}
+
+\section{July 2012}
+
+\begin{itemize}
+  \item The \cs{tl_if_head_eq_meaning:nN}, \cs{tl_if_head_eq_catcode:nN}
+    and \cs{tl_if_head_eq_charcode:nN} conditionals now never match when
+    their first argument is empty.
+\end{itemize}
+
+\section{August 2012}
+
+\begin{itemize}
+  \item \cs{lua_now:x} is now a standard \texttt{x}-type expansion of
+    \cs{lua_now:n}, which does no expansion. Engine-level expansion is moved
+    to \cs{lua_now:e}, reflecting the fact that this is non-standard in the
+    same way as for example \cs{str_if_eq_x:nn(TF)}.
+\end{itemize}
+
+\section{December 2013}
+
+\begin{itemize}
+  \item In \pkg{l3fp} expressions, the badly named functions |round0|,
+    |round-|, |round+| are now named |trunc|, |floor|, |ceil|.
+\end{itemize}
+
+\section{May 2014}
+
+\begin{itemize}
+  \item Now \cs{int_step_function:nnnN} evaluates its first three
+    arguments (start, step, stop) up front, rather than evaluating them
+    at each step in the loop.  The same holds for the related mappings
+    \cs{int_step_inline:nnnn}, \cs{int_step_variable:nnnNn}, and their
+    analogues for \texttt{dim} and \texttt{fp} datatypes.
+\end{itemize}
+
+\section{July 2014}
+
+\begin{itemize}
+  \item In \pkg{l3fp} expressions, juxtaposition is interpreted as
+    multiplication.  Now the precedence of juxtaposition is set to be
+    the same as if there was an explicit multiplication
+    sign~\texttt{*}.  Previously, juxtaposition would bound more tightly
+    than any other operation.
+\end{itemize}
+
+\section{August 2015}
+
+\begin{itemize}
+  \item The \cs{hbox:n} and related \pkg{l3box} commands now take an
+    \texttt{n}-type argument and provide it braced to the underlying
+    \TeX{} primitive.  The functions \cs{hbox:w} and \cs{hbox_end:} in
+    contrast do not read the contents of the box as a macro argument.
+\end{itemize}
+
+\section{2016}
+
+No change.
+
+\section{July 2017}
+
+\begin{itemize}
+  \item Boolean expressions are now evaluated eagerly, namely both
+    operands of logical \texttt{and} (|&&|) and \texttt{or} (\verb"||")
+    are evaluated even when the result of the logical operation is fixed
+    after determining the first operand.  For lazy evaluation,
+    \cs{bool_lazy_and_p:nn} and related functions are provided.
+\end{itemize}
+
+\section{November 2017}
+
+\begin{itemize}
+  \item Spaces are now preserved inside keys in \pkg{l3keys}, and
+    trimmed at both ends.
+  \item \cs{cs_generate_variant:Nn} is now stricter: it only allows to
+    change \texttt{N}-type arguments to \texttt{c}, and \texttt{n} to
+    \texttt{o}, \texttt{V}, \texttt{v}, \texttt{f}, \texttt{x}.  On the
+    one hand the latter argument types typically give rise to more than
+    one token, not suitable for use by an \texttt{N}-type base function.
+    On the other hand, \texttt{c} variants of \texttt{n} arguments
+    should often be \texttt{v} variants (when the argument is eventually
+    evaluated) or mistakes where the programmer thought the base
+    function was \texttt{N}-type.
+\end{itemize}
+
+\section{February 2020}
+
+\begin{itemize}
+  \item \cs{keyval_parse:NNn} now works by expansion, returning
+    the parsed list inside \cs{exp_not:n}.
+\end{itemize}
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3syntax-changes.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,180 @@
+\iffalse meta-comment
+
+File: l3term-glossary.tex
+
+Copyright (C) 2018-2024 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 released version of this bundle is available from CTAN.
+
+\fi
+
+\documentclass{l3doc}
+
+
+\title{%
+  Glossary of \TeX{} terms used to describe \LaTeX3 functions%
+}
+\author{%
+  The \LaTeX{} Project\thanks
+    {%
+      E-mail:
+      \href{mailto:latex-team at latex-project.org}%
+        {latex-team at latex-project.org}%
+    }%
+}
+\date{Released 2024-04-11}
+
+\newcommand{\TF}{\textit{(TF)}}
+
+\begin{document}
+
+\maketitle
+
+This file describes aspects of \TeX{} programming that are relevant in a
+\pkg{expl3} context.
+
+\section{Reading a file}
+
+Tokenization.
+
+Treatment of spaces, such as the trap that \verb|\~~a| is equivalent to
+\verb|\~a| in \pkg{expl3} syntax, or that \verb|~| fails to give a space at the
+beginning of a line.
+
+\section{Structure of tokens}
+
+We refer to the documentation of \texttt{l3token} for a complete
+description of all \TeX{} tokens.  We distinguish the meaning of the
+token, which controls the expansion of the token and its effect on
+\TeX{}'s state, and its shape, which is used when comparing token lists
+such as for delimited arguments.  At any given time two tokens of the
+same shape automatically have the same meaning, but the converse does
+not hold, and the meaning associated with a given shape change when
+doing assignments.
+
+Apart from a few exceptions, a token has one of the following shapes.
+\begin{itemize}
+  \item A control sequence, characterized by the sequence of characters
+    that constitute its name: for instance, \cs{use:n} is a five-letter
+    control sequence.
+  \item An active character token, characterized by its character code
+    (between $0$ and $1114111$ for \LuaTeX{} and \XeTeX{} and less for
+    other engines) and category code~$13$.
+  \item A character token such as |A| or |#|, characterized by its
+    character code and category code (one of $1$, $2$, $3$, $4$, $6$,
+    $7$, $8$, $10$, $11$ or~$12$ whose meaning is described below).
+\end{itemize}
+
+The meaning of a (non-active) character token is fixed by its category
+code (and character code) and cannot be changed.  We call these tokens
+\emph{explicit} character tokens.  Category codes that a character token
+can have are listed below by giving a sample output of the \TeX{}
+primitive \tn{meaning}, together with their \pkg{expl3} names and most
+common example:
+\begin{itemize}
+  \item[1] begin-group character (|group_begin|, often |{|),
+  \item[2] end-group character (|group_end|, often |}|),
+  \item[3] math shift character (|math_toggle|, often |$|), % $
+  \item[4] alignment tab character (|alignment|, often |&|),
+  \item[6] macro parameter character (|parameter|, often |#|),
+  \item[7] superscript character (|math_superscript|, often |^|),
+  \item[8] subscript character (|math_subscript|, often |_|),
+  \item[10] blank space (|space|, often character code~$32$),
+  \item[11] the letter (|letter|, such as |A|),
+  \item[12] the character (|other|, such as |0|).
+\end{itemize}
+Category code~$13$ (|active|) is discussed below.  Input characters can
+also have several other category codes which do not lead to character
+tokens for later processing: $0$~(|escape|), $5$~(|end_line|),
+$9$~(|ignore|), $14$~(|comment|), and $15$~(|invalid|).
+
+The meaning of a control sequence or active character can be identical
+to that of any character token listed above (with any character code),
+and we call such tokens \emph{implicit} character tokens.  The meaning
+is otherwise in the following list:
+\begin{itemize}
+  \item a macro, used in \pkg{expl3} for most functions and some variables
+    (|tl|, |fp|, |seq|, \ldots{}),
+  \item a primitive such as \tn{def} or \tn{topmark}, used in \pkg{expl3}
+    for some functions,
+  \item a register such as \tn{count}|123|, used in \pkg{expl3} for the
+    implementation of some variables (|int|, |dim|, \ldots{}),
+  \item a constant integer such as \tn{char}|"56| or
+    \tn{mathchar}|"121|, used when defining a constant using
+    \cs{int_const:Nn},
+  \item a font selection command,
+  \item undefined.
+\end{itemize}
+Macros can be \tn{protected} or not, \tn{long} or not (the opposite of
+what \pkg{expl3} calls |nopar|), and \tn{outer} or not (unused in \pkg{expl3}).
+Their \tn{meaning} takes the form
+\begin{quote}
+  \meta{prefix} |macro:|\meta{argument}|->|\meta{replacement}
+\end{quote}
+where \meta{prefix} is among \tn{protected}\tn{long}\tn{outer},
+\meta{argument} describes parameters that the macro expects, such as
+|#1#2#3|, and \meta{replacement} describes how the parameters are
+manipulated, such as~|\int_eval:n{#2+#1*#3}|.  This information can be
+accessed by \cs{cs_prefix_spec:N}, \cs{cs_parameter_spec:N},
+\cs{cs_replacement_spec:N}.
+
+When a macro takes an undelimited argument, explicit space characters
+(with character code $32$ and category code $10$) are ignored.  If the
+following token is an explicit character token with category code $1$
+(begin-group) and an arbitrary character code, then \TeX{} scans ahead
+to obtain an equal number of explicit character tokens with category
+code $1$ (begin-group) and $2$ (end-group), and the resulting list of
+tokens (with outer braces removed) becomes the argument.  Otherwise, a
+single token is taken as the argument for the macro: we call such single
+tokens \enquote{N-type}, as they are suitable to be used as an argument
+for a function with the signature~\texttt{:N}.
+
+When a macro takes a delimited argument \TeX{} scans ahead until finding
+the delimiter (outside any pairs of begin-group/end-group explicit
+characters), and the resulting list of tokens (with outer braces
+removed) becomes the argument.  Note that explicit space characters at
+the start of the argument are \emph{not} ignored in this case (and they
+prevent brace-stripping).
+
+\section{Handling of hash tokens}
+
+\TeX{} uses the hash (octothorpe) character |#| to denote parameters for
+macros: these must be numbered sequentially. To allow handling of nested
+macros, \TeX{} requires that for each nesting level, hash tokens are doubled.
+For example
+\begin{verbatim}
+\cs_new:Npn \mypkg_outer:N #1
+  {
+    \cs_new:Npn \mypkg_inner:N ##1
+      {
+        #1
+        ##1
+      }
+  }
+\end{verbatim}
+would define both |\mypkg_outer:N| and |\mypkg_inner:N| as taking
+exactly one argument. If we then do
+\begin{verbatim}
+\mypkg_outer:N \foo
+\cs_show:N \mypkg_inner:N
+\end{verbatim}
+\TeX{} will report
+\begin{verbatim}
+> \mypkg_inner:N=\long macro:#1->\foo #1.
+\end{verbatim}
+i.e.~the hash is not doubled, but is now the parameter of this macro.
+
+Exactly the same concept applies to anywhere that inline code is nested in
+\pkg{expl3}, for example inline mapping code, key definitions, etc.
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/l3term-glossary.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.pdf	2024-04-18 03:35:47 UTC (rev 70975)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.pdf	2024-04-18 19:48:25 UTC (rev 70976)

Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,106 @@
+\iffalse meta-comment
+
+File: source3.tex
+
+Copyright (C) 1990-2012,2017-2024 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 released version of this bundle is available from CTAN.
+
+-----------------------------------------------------------------------
+
+The development version of the bundle can be found at
+
+   https://github.com/latex3/latex3
+
+for those people who are interested.
+
+\fi
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% This document typesets the LaTeX3 sources as a single document.
+% This produces quite a large file (more than 1670 pages as of Dec 2023).
+%
+% There is also a shorter version (interface3.tex) that only typesets the
+% command % interface descriptions.
+%
+% Do not forget to generate the index (as explained on the terminal output
+% near the end of the run)!
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\documentclass[kernel]{l3doc}
+
+\newif\ifinterface
+\interfacefalse
+
+\listfiles
+
+\begin{document}
+
+\title{The \LaTeX3 Sources}
+\author{%
+ The \LaTeX{} Project\thanks
+   {%
+     E-mail:
+       \href{mailto:latex-team at latex-project.org}
+         {latex-team at latex-project.org}%
+   }%
+}
+\date{Released 2024-04-11}
+
+\pagenumbering{roman}
+\maketitle
+
+%
+% First load all modules and typeset the documentation parts
+%
+
+\input{source3body}    % all the individual modules
+
+%
+% Now reload all modules and typeset the implementation parts
+%
+
+\part{Implementation}
+
+\def\maketitle{}
+\let\subsubsection\subsection
+\let\subsection\section
+\let\section\chapter
+
+\EnableImplementation
+\DisableDocumentation
+\DocInputAgain
+
+\clearpage
+\pagestyle{headings}
+
+% Make TeX shut up.
+\hbadness=10000
+\newcount\hbadness
+\hfuzz=\maxdimen
+
+\PrintChanges
+\clearpage
+
+\begingroup
+  \def\endash{--}
+  \catcode`\-\active
+  \def-{\futurelet\temp\indexdash}
+  \def\indexdash{\ifx\temp-\endash\fi}
+
+  \DelayPrintIndex
+\endgroup
+
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3body.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3body.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3body.tex	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,620 @@
+\iffalse meta-comment
+
+File: source3body.tex
+
+Copyright (C) 1990-2012,2014-2023 The LaTeX Project
+
+It may be distributed and/or modified under the conditions of the
+LaTeX Project Public License (LPPL), either version 1.3c of this
+license or (at your option) any later version.  The latest version
+of this license is in the file
+
+   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 released version of this bundle is available from CTAN.
+
+-----------------------------------------------------------------------
+
+The development version of the bundle can be found at
+
+   https://github.com/latex3/latex3
+
+for those people who are interested.
+
+\fi
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% This file is used by
+%
+%  source3.tex            % documentation including implementation
+%
+%  interface3.tex         % only interface documentation
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+\begin{abstract}
+
+\setlength\parindent{0pt}
+\setlength\parskip{\baselineskip}
+
+\noindent
+\ifinterface
+This is the reference documentation for the \pkg{expl3}
+programming environment; see the matching \pkg{source3} PDF
+for the typeset sources.
+\else
+This is the typset sources for the \pkg{expl3}
+programming environment; see the matching \pkg{interface3} PDF
+for the API reference manual.
+\fi
+The \pkg{expl3} modules set up a
+naming scheme for \LaTeX{} commands, which allow the \LaTeX{} programmer
+to systematically name functions and variables, and specify the argument
+types of functions.
+
+The \TeX{} and \eTeX{} primitives are all given a new name according to
+these conventions. However, in the main direct use of the primitives is
+not required or encouraged: the \pkg{expl3} modules define an
+independent low-level \LaTeX3 programming language.
+
+The \pkg{expl3} modules are designed to be loaded on top of
+\LaTeXe{}. With an up-to-date \LaTeXe{} kernel, this material is loaded
+as part of the format. The fundamental programming code can also be loaded
+with other \TeX{} formats, subject to restrictions on the full range of
+functionality.
+
+\end{abstract}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Each of the following \DocInput lines includes a file with extension
+% .dtx. Each of these files may be typeset separately. For instance
+%   pdflatex l3box.dtx
+% will typeset the source of the LaTeX3 box commands. If you use the
+% Makefile, the index will be generated automatically; e.g.,
+%   make doc F=l3box
+%
+% If this file is processed, each of these separate dtx files will be
+% contained as a part of a single document.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\makeatletter
+% l3doc is based on article, but for these very large documents we need
+% chapters; the code is based on the standard classes but somewhat simplified
+\renewcommand\part{%
+    \clearpage
+  \thispagestyle{plain}%
+  \@tempswafalse
+  \null\vfil
+  \secdef\@part\@spart}
+\newcounter {chapter}
+\numberwithin{section}{chapter}
+\renewcommand \thechapter {\@arabic\c at chapter}
+\renewcommand \thesection {\thechapter.\@arabic\c at section}
+\newcommand*\chaptermark[1]{}
+\setcounter{secnumdepth}{2}
+\newcommand\@chapapp{\chaptername}
+\newcommand\chaptername{Chapter}
+  \def\ps at headings{%
+    \let\@oddfoot\@empty
+    \def\@oddhead{{\slshape\rightmark}\hfil\thepage}%
+    \let\@mkboth\markboth
+    \def\chaptermark##1{%
+      \markright {\MakeUppercase{%
+        \ifnum \c at secnumdepth >\m at ne
+            \@chapapp\ \thechapter. \ %
+        \fi
+        ##1}}}}
+\newcommand\chapter{\clearpage
+                    \thispagestyle{plain}%
+                    \global\@topnum\z@
+                    \@afterindentfalse
+                    \secdef\@chapter\@schapter}
+\def\@chapter[#1]#2{\refstepcounter{chapter}%
+                    \typeout{\@chapapp\space\thechapter.}%
+                    \addcontentsline{toc}{chapter}%
+                      {\protect\numberline{\thechapter}#1}%
+                    \chaptermark{#1}%
+                    \addtocontents{lof}{\protect\addvspace{10\p@}}%
+                    \addtocontents{lot}{\protect\addvspace{10\p@}}%
+                    \@makechapterhead{#2}%
+                    \@afterheading}
+\def\@makechapterhead#1{%
+  \vspace*{50\p@}%
+  {\parindent \z@ \raggedright \normalfont
+   \huge\bfseries \@chapapp\space \thechapter
+   \par\nobreak
+   \vskip 20\p@
+    \interlinepenalty\@M
+    \Huge \bfseries #1\par\nobreak
+    \vskip 40\p@
+  }}
+\newcommand*\l at chapter[2]{%
+  \ifnum \c at tocdepth >\m at ne
+    \addpenalty{-\@highpenalty}%
+    \vskip 1.0em \@plus\p@
+    \setlength\@tempdima{1.5em}%
+    \begingroup
+      \parindent \z@ \rightskip \@pnumwidth
+      \parfillskip -\@pnumwidth
+      \leavevmode \bfseries
+      \advance\leftskip\@tempdima
+      \hskip -\leftskip
+      #1\nobreak\hfil
+      \nobreak\hb at xt@\@pnumwidth{\hss #2%
+                                 \kern-\p@\kern\p@}\par
+      \penalty\@highpenalty
+    \endgroup
+  \fi}
+\renewcommand*\l at section{\@dottedtocline{1}{1.5em}{2.8em}}
+\renewcommand*\l at subsection{\@dottedtocline{2}{3.8em}{3.2em}}
+\renewcommand*\l at subsubsection{\@dottedtocline{3}{7.0em}{4.1em}}
+\def\partname{Part}
+\def\toclevel at part{-1}
+\def\maketitle{\chapter{\@title}}
+\let\thanks\@gobble
+\let\DelayPrintIndex\PrintIndex
+\let\PrintIndex\@empty
+\providecommand*{\hexnum}[1]{\text{\texttt{\char`\"}#1}}
+\makeatother
+
+\clearpage
+
+{%
+  \def\\{:}% fix "newlines" in the ToC
+  \tableofcontents
+}
+
+\clearpage
+\pagenumbering{arabic}
+
+\part{Introduction}
+
+\chapter{Introduction to \pkg{expl3} and this document}
+
+This document is intended to act as a comprehensive reference manual
+for the \pkg{expl3} language. A general guide to the \LaTeX3
+programming language is found in \href{expl3.pdf}{expl3.pdf}.
+
+\section{Naming functions and variables}
+
+\LaTeX3 does not use \texttt{@} as a \enquote{letter} for defining
+internal macros.  Instead, the symbols |_| and \texttt{:}
+are used in internal macro names to provide structure. The name of
+each \emph{function} is divided into logical units using \texttt{_},
+while \texttt{:} separates the \emph{name} of the function from the
+\emph{argument specifier} (\enquote{arg-spec}). This describes the arguments
+expected by the function. In most cases, each argument is represented
+by a single letter. The complete list of arg-spec letters for a function
+is referred to as the \emph{signature} of the function.
+
+Each function name starts with the \emph{module} to which it belongs.
+Thus apart from a small number of very basic functions, all \pkg{expl3}
+function names contain at least one underscore to divide the module
+name from the descriptive name of the function. For example, all
+functions concerned with comma lists are in module \texttt{clist} and
+begin |\clist_|.
+
+Every function must include an argument specifier. For functions which
+take no arguments, this will be blank and the function name will end
+\texttt{:}. Most functions take one or more arguments, and use the
+following argument specifiers:
+\begin{description}
+  \item[\texttt{N} and \texttt{n}] These mean \emph{no manipulation},
+    of a single token for \texttt{N} and of a set of tokens given in
+    braces for \texttt{n}. Both pass the argument through exactly as
+    given. Usually, if you use a single token for an \texttt{n} argument,
+    all will be well.
+  \item[\texttt{c}] This means \emph{csname}, and indicates that the
+    argument will be turned into a csname before being used. So
+    |\foo:c| |{ArgumentOne}| will act in the same way as |\foo:N|
+    |\ArgumentOne|. All macros that appear in the argument are expanded.
+    An internal error will occur if the result of expansion inside
+    a \texttt{c}-type argument is not a series of character tokens.
+  \item[\texttt{V} and \texttt{v}] These mean \emph{value
+    of variable}. The \texttt{V} and \texttt{v} specifiers are used to
+    get the content of a variable without needing to worry about the
+    underlying \TeX{} structure containing the data. A \texttt{V}
+    argument will be a single token (similar to \texttt{N}), for example
+    |\foo:V| |\MyVariable|; on the other hand, using \texttt{v} a
+    csname is constructed first, and then the value is recovered, for
+    example |\foo:v| |{MyVariable}|.
+  \item[\texttt{o}] This means \emph{expansion once}. In general, the
+    \texttt{V} and \texttt{v} specifiers are favoured over \texttt{o}
+    for recovering stored information. However, \texttt{o} is useful
+    for correctly processing information with delimited arguments.
+  \item[\texttt{x}] The \texttt{x} specifier stands for \emph{exhaustive
+    expansion}: every token in the argument is fully expanded until only
+    unexpandable ones remain. The \TeX{} \tn{edef} primitive carries out
+    this type of expansion. Functions which feature an \texttt{x}-type
+    argument are \emph{not} expandable.
+  \item[\texttt{e}] The \texttt{e} specifier is in many respects
+    identical to \texttt{x}, but uses \tn{expanded} primitive.
+    Parameter character (usually~|#|) in the argument need not be doubled.
+    Functions which feature an \texttt{e}-type argument may be
+    expandable.
+  \item[\texttt{f}] The \texttt{f} specifier stands for \emph{full
+    expansion}, and in contrast to \texttt{x} stops at the first
+    non-expandable token (reading the argument from left to right) without
+    trying to expand it. If this token is a \meta{space token}, it is gobbled,
+    and thus won't be part of the resulting argument. For example, when
+    setting a token list variable (a macro used for storage), the sequence
+    \begin{verbatim}
+      \tl_set:Nn \l_mya_tl { A }
+      \tl_set:Nn \l_myb_tl { B }
+      \tl_set:Nf \l_mya_tl { \l_mya_tl \l_myb_tl }
+    \end{verbatim}
+    will leave |\l_mya_tl| with the content |A\l_myb_tl|, as |A| cannot
+    be expanded and so terminates expansion before |\l_myb_tl| is considered.
+  \item[\texttt{T} and \texttt{F}] For logic tests, there are the branch
+    specifiers \texttt{T} (\emph{true}) and \texttt{F} (\emph{false}).
+    Both specifiers treat the input in the same way as \texttt{n} (no
+    change), but make the logic much easier to see.
+  \item[\texttt{p}] The letter \texttt{p} indicates \TeX{}
+    \emph{parameters}. Normally this will be used for delimited
+    functions as \pkg{expl3} provides better methods for creating simple
+    sequential arguments.
+  \item[\texttt{w}] Finally, there is the \texttt{w} specifier for
+    \emph{weird} arguments. This covers everything else, but mainly
+    applies to delimited values (where the argument must be terminated
+    by some specified string).
+  \item[\texttt{D}] The \texttt{D} stands for \textbf{Do not use}.
+    All of the \TeX{} primitives are initially \cs[no-index]{let} to a \texttt{D}
+    name, and some are then given a second name.
+    These functions have no standardized syntax, they are engine
+    dependent and their name can change without warning, thus their
+    use is \emph{strongly discouraged} in package code: programmers
+    should instead use the interfaces documented in
+    \ifinterface
+      this documentation.
+    \else
+      \href{interface3.pdf}{interface3.pdf}.
+    \fi
+\end{description}
+Notice that the argument specifier describes how the argument is
+processed prior to being passed to the underlying function. For example,
+|\foo:c| will take its argument, convert it to a control sequence and
+pass it to |\foo:N|.
+
+Variables are named in a similar manner to functions, but begin with
+a single letter to define the type of variable:
+\begin{description}
+  \item[\texttt{c}] Constant: global parameters whose value should not
+    be changed.
+  \item[\texttt{g}] Parameters whose value should only be set globally.
+  \item[\texttt{l}] Parameters whose value should only be set locally.
+\end{description}
+Each variable name is then build up in a similar way to that of a
+function, typically starting with the module\footnote{The module names are
+  not used in case of generic scratch registers defined in the data
+  type modules, e.g., the
+  \texttt{int} module contains some scratch variables called \cs{l_tmpa_int},
+  \cs{l_tmpb_int}, and so on. In such a case adding the module name up front
+  to denote the module
+  and in the back to indicate the type, as in
+  \texttt{\string\l_int_tmpa_int} would be very unreadable.}  name
+and then a descriptive part.
+Variables end with a short identifier to show the variable type:
+\begin{description}%  
+  \item[\texttt{bitset}] a set of bits (a string made up of a series of \texttt{0}
+    and \texttt{1} tokens that are accessed by position).
+  \item[\texttt{clist}] Comma separated list.
+  \item[\texttt{dim}] \enquote{Rigid} lengths.
+  \item[\texttt{fp}] Floating-point values;
+  \item[\texttt{int}] Integer-valued count register.
+  \item[\texttt{muskip}] \enquote{Rubber} lengths for use in
+    mathematics.
+  \item[\texttt{skip}] \enquote{Rubber} lengths.
+  \item[\texttt{str}] String variables: contain character data.
+  \item[\texttt{tl}] Token list variables: placeholder for a token list.
+\end{description}
+Applying \texttt{V}-type or \texttt{v}-type expansion to variables of
+one of the above types is supported, while it is not supported for the
+following variable types:
+\begin{description}
+  \item[\texttt{bool}] Either true or false.
+  \item[\texttt{box}] Box register.
+  \item[\texttt{coffin}] A \enquote{box with handles} --- a higher-level
+    data type for carrying out \texttt{box} alignment operations.
+  \item[\texttt{flag}] Non-negative integer that can be incremented expandably.
+  \item[\texttt{fparray}] Fixed-size array of floating point values.
+  \item[\texttt{intarray}] Fixed-size array of integers.
+  \item[\texttt{ior}/\texttt{iow}] An input or output stream, for
+    reading from or writing to, respectively.
+  \item[\texttt{prop}] Property list: analogue of dictionary or
+    associative arrays in other languages.
+  \item[\texttt{regex}] Regular expression.
+  \item[\texttt{seq}] \enquote{Sequence}: a data type used to implement
+    lists (with access at both ends) and stacks.
+\end{description}
+
+\subsection{Scratch variables}
+
+Modules focussed on variable usage typically provide four scratch variables,
+two local and two global, with names of the form
+\cs[no-index]{\meta{scope}_tmpa_\meta{type}}/\cs[no-index]{\meta{scope}_tmpb_\meta{type}}. These
+are never used by the core code. The nature of \TeX{} grouping means that as
+with any other scratch variable, these should only be set and used with no
+intervening third-party code.
+
+\subsection{Terminological inexactitude}
+
+A word of warning. In this document, and others referring to the \pkg{expl3}
+programming modules, we often refer to \enquote{variables} and
+\enquote{functions} as if they
+were actual constructs from a real programming language.  In truth, \TeX{}
+is a macro processor, and functions are simply macros that may or may not take
+arguments and expand to their replacement text.  Many of the common variables
+are \emph{also} macros, and if placed into the input stream will simply expand
+to their definition as well~--- a \enquote{function} with no arguments and a
+\enquote{token list variable} are almost the same.\footnote{\TeX{}nically,
+functions with no arguments are \tn{long} while token list variables are not.}
+On the other
+hand, some \enquote{variables} are actually registers that must be
+initialised and their values set and retrieved with specific functions.
+
+The conventions of the \pkg{expl3} code are designed to clearly separate the
+ideas of \enquote{macros that contain data} and
+\enquote{macros that contain code}, and a
+consistent wrapper is applied to all forms of \enquote{data} whether they be
+macros or
+actually registers.  This means that sometimes we will use phrases like
+\enquote{the function returns a value}, when actually we just mean
+\enquote{the macro expands to something}. Similarly, the term
+\enquote{execute} might be used in place of \enquote{expand}
+or it might refer to the more specific case of
+\enquote{processing in \TeX's stomach}
+(if you are familiar with the \TeX{}book parlance).
+
+If in doubt, please ask; chances are we've been hasty in writing certain
+definitions and need to be told to tighten up our terminology.
+
+\section{Documentation conventions}
+
+This document is typeset with the experimental \pkg{l3doc} class;
+several conventions are used to help describe the features of the code.
+A number of conventions are used here to make the documentation clearer.
+
+Each group of related functions is given in a box. For a function with
+a \enquote{user} name, this might read:
+\begin{function}[label = ]{\ExplSyntaxOn, \ExplSyntaxOff}
+  \begin{syntax}
+    |\ExplSyntaxOn| \dots{} |\ExplSyntaxOff|
+  \end{syntax}
+  The textual description of how the function works would appear here. The
+  syntax of the function is shown in mono-spaced text to the right of
+  the box. In this example, the function takes no arguments and so the
+  name of the function is simply reprinted.
+\end{function}
+
+For programming functions, which use \texttt{_} and \texttt{:} in their name
+there are a few additional conventions: If two related functions are given
+with identical names but different argument specifiers, these are termed
+\emph{variants} of each other, and the latter functions are printed in grey to
+show this more clearly. They will carry out the same function but will take
+different types of argument:
+\begin{function}[label = ]{\seq_new:N, \seq_new:c}
+  \begin{syntax}
+    |\seq_new:N| \meta{sequence}
+  \end{syntax}
+  When a number of variants are described, the arguments are usually
+  illustrated only for the base function. Here, \meta{sequence} indicates
+  that |\seq_new:N| expects the name of a sequence. From the argument
+  specifier, |\seq_new:c| also expects a sequence name, but as a
+  name rather than as a control sequence. Each argument given in the
+  illustration should be described in the following text.
+\end{function}
+
+\paragraph{Fully expandable functions}
+\hypertarget{expstar}{Some functions are fully expandable},
+which allows them to be used within
+an \texttt{x}-type or \texttt{e}-type argument (in plain \TeX{} terms, inside an \tn{edef} or \tn{expanded}),
+as well as within an \texttt{f}-type argument.
+These fully expandable functions are indicated in the documentation by
+a star:
+\begin{function}[EXP, label = ]{\cs_to_str:N}
+  \begin{syntax}
+    |\cs_to_str:N| \meta{cs}
+  \end{syntax}
+  As with other functions, some text should follow which explains how
+  the function works. Usually, only the star will indicate that the
+  function is expandable. In this case, the function expects a \meta{cs},
+  shorthand for a \meta{control sequence}.
+\end{function}
+
+\paragraph{Restricted expandable functions}
+\hypertarget{rexpstar}{A few functions are fully expandable} but cannot be fully expanded within
+an \texttt{f}-type argument. In this case a hollow star is used to indicate
+this:
+\begin{function}[rEXP, label = ]{\seq_map_function:NN}
+  \begin{syntax}
+    |\seq_map_function:NN| \meta{seq} \meta{function}
+  \end{syntax}
+\end{function}
+
+\paragraph{Conditional functions}
+\hypertarget{explTF}{Conditional (\texttt{if}) functions}
+are normally defined in three variants, with
+\texttt{T}, \texttt{F} and \texttt{TF} argument specifiers. This allows
+them to be used for different \enquote{true}/\enquote{false} branches,
+depending on
+which outcome the conditional is being used to test. To indicate this
+without repetition, this information is given in a shortened form:
+\begin{function}[EXP,TF, label = ]{\sys_if_engine_xetex:}
+  \begin{syntax}
+    |\sys_if_engine_xetex:TF| \Arg{true code} \Arg{false code}
+  \end{syntax}
+  The underlining and italic of \texttt{TF} indicates that three functions
+  are available:
+  \begin{itemize}
+    \item |\sys_if_engine_xetex:T|
+    \item |\sys_if_engine_xetex:F|
+    \item |\sys_if_engine_xetex:TF|
+  \end{itemize}
+  Usually, the illustration
+  will use the \texttt{TF} variant, and so both \meta{true code}
+  and \meta{false code} will be shown. The two variant forms \texttt{T} and
+  \texttt{F} take only \meta{true code} and \meta{false code}, respectively.
+  Here, the star also shows that this function is expandable.
+  With some minor exceptions, \emph{all} conditional functions in the
+  \pkg{expl3} modules should be defined in this way.
+\end{function}
+
+Variables, constants and so on are described in a similar manner:
+\begin{variable}[label = ]{\l_tmpa_tl}
+  A short piece of text will describe the variable: there is no
+  syntax illustration in this case.
+\end{variable}
+
+In some cases, the function is similar to one in \LaTeXe{} or plain \TeX{}.
+In these cases, the text will include an extra \enquote{\textbf{\TeX{}hackers
+note}} section:
+\begin{function}[EXP, label = ]{\token_to_str:N}
+  \begin{syntax}
+    |\token_to_str:N| \meta{token}
+  \end{syntax}
+  The normal description text.
+  \begin{texnote}
+    Detail for the experienced \TeX{} or \LaTeXe\ programmer. In this
+    case, it would point out that this function is the \TeX{} primitive
+    |\string|.
+  \end{texnote}
+\end{function}
+
+\paragraph{Changes to behaviour}
+When new functions are added to \pkg{expl3}, the date of first inclusion is
+given in the documentation. Where the documented behaviour of a function
+changes after it is first introduced, the date of the update will also be
+given. This means that the programmer can be sure that any release of
+\pkg{expl3} after the date given will contain the function of interest with
+expected behaviour as described. Note that changes to code internals, including
+bug fixes, are not recorded in this way \emph{unless} they impact on the
+expected behaviour.
+
+\section{Formal language conventions which apply generally}
+
+As this is a formal reference guide for \LaTeX3 programming, the descriptions
+of functions are intended to be reasonably \enquote{complete}. However, there
+is also a need to avoid repetition. Formal ideas which apply to general
+classes of function are therefore summarised here.
+
+For tests which have a \texttt{TF} argument specification, the test if
+evaluated to give a logically \texttt{TRUE} or \texttt{FALSE} result.
+Depending on this result, either the \meta{true code} or the \meta{false code}
+will be left in the input stream. In the case where the test is expandable,
+and a predicate (|_p|) variant is available, the logical value determined by
+the test is left in the input stream: this will typically be part of a larger
+logical construct.
+
+\section{\TeX{} concepts not supported by \LaTeX3{}}
+
+The \TeX{} concept of an \enquote{\tn{outer}} macro is \emph{not supported}
+at all by \LaTeX3{}. As such, the functions provided here may break when
+used on top of \LaTeXe{} if \tn{outer} tokens are used in the arguments.
+
+\DisableImplementation
+
+\part{Bootstrapping}
+
+\DocInput{l3bootstrap.dtx}
+\DocInput{l3names.dtx}
+\ExplSyntaxOn
+\clist_gput_right:Nn \g_docinput_clist { l3kernel-functions.dtx }
+\ExplSyntaxOff
+
+\part{Programming Flow}
+
+\DocInput{l3basics.dtx}
+\DocInput{l3expan.dtx}
+\DocInput{l3sort.dtx}
+\DocInput{l3tl-analysis.dtx}
+\DocInput{l3regex.dtx}
+\DocInput{l3prg.dtx}
+\DocInput{l3sys.dtx}
+\DocInput{l3msg.dtx}
+\DocInput{l3file.dtx}
+
+\DocInput{l3luatex.dtx}
+
+\DocInput{l3legacy.dtx}
+
+
+\part{Data types}
+
+\DocInput{l3tl.dtx}
+\DocInput{l3tl-build.dtx}
+\DocInput{l3str.dtx}
+\DocInput{l3str-convert.dtx}
+\DocInput{l3quark.dtx}
+\DocInput{l3seq.dtx}
+\DocInput{l3int.dtx}
+\DocInput{l3flag.dtx}
+\DocInput{l3clist.dtx}
+\DocInput{l3token.dtx}
+\DocInput{l3prop.dtx}
+\DocInput{l3skip.dtx}
+\DocInput{l3keys.dtx}
+\DocInput{l3intarray.dtx}
+\DocInput{l3fp.dtx}
+% To get the various submodules of l3fp to appear in the implementation
+% part only, they have to be added to the documentation list after typesetting
+% the 'user' part just for the main module.
+\ExplSyntaxOn
+\clist_gput_right:Nn \g_docinput_clist
+  {
+    l3fp-aux.dtx ,
+    l3fp-traps.dtx ,
+    l3fp-round.dtx ,
+    l3fp-parse.dtx ,
+    l3fp-assign.dtx ,
+    l3fp-logic.dtx ,
+    l3fp-basics.dtx ,
+    l3fp-extended.dtx ,
+    l3fp-expo.dtx ,
+    l3fp-trig.dtx ,
+    l3fp-convert.dtx ,
+    l3fp-random.dtx ,
+    l3fp-types.dtx ,
+    l3fp-symbolic.dtx ,
+    l3fp-functions.dtx
+  }
+\ExplSyntaxOff
+
+\DocInput{l3fparray.dtx}
+\DocInput{l3bitset.dtx}
+\DocInput{l3cctab.dtx}
+
+\part{Text manipulation}
+
+\DocInput{l3unicode.dtx}
+\DocInput{l3text.dtx}
+\ExplSyntaxOn
+\clist_gput_right:Nn \g_docinput_clist
+  {
+    l3text-case.dtx ,
+    l3text-map.dtx  ,
+    l3text-purify.dtx
+  }
+\ExplSyntaxOff
+
+\part{Typesetting}
+
+\DocInput{l3box.dtx}
+\DocInput{l3coffins.dtx}
+\DocInput{l3color.dtx}
+\DocInput{l3pdf.dtx}
+
+% implementation part only
+\ExplSyntaxOn
+\clist_gput_right:Nn \g_docinput_clist { l3deprecation.dtx }
+\clist_gput_right:Nn \g_docinput_clist { l3debug.dtx }
+\ExplSyntaxOff
+
+\endinput


Property changes on: trunk/Master/texmf-dist/doc/latex-dev/l3kernel/source3body.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/expl3.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/expl3.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/expl3.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,1798 @@
+% \iffalse meta-comment
+%
+%% File: expl3.dtx
+%
+% Copyright (C) 1990-2024 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|generic|package|2ekernel>
+%</driver|generic|package|2ekernel>
+\def\ExplFileDate{2024-04-11}%
+%<*driver>
+\documentclass[full]{l3doc}
+\usepackage{graphicx}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \providecommand\acro[1]{\textsc{\MakeLowercase{#1}}}
+% \newenvironment{arg-description}{%
+%   \begin{itemize}\def\makelabel##1{\hss\llap{\bfseries##1}}}{\end{itemize}}
+%
+% \title{^^A
+%   The \pkg{expl3} package and \LaTeX3 programming^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \begin{abstract}
+%
+% This document gives an introduction to a new set of programming
+% conventions that have been designed to meet the requirements of
+% implementing large scale \TeX{} macro programming projects such as
+% \LaTeX{}. These programming conventions are the base layer of \LaTeX3.
+%
+% The main features of the system described are:
+% \begin{itemize}
+%   \item classification of the macros (or, in \LaTeX{} terminology,
+%     commands) into \LaTeX{} functions and \LaTeX{} parameters, and also
+%     into modules containing related commands;
+%   \item  a systematic naming scheme based on these classifications;
+%   \item  a simple mechanism for controlling the expansion of a function's
+%     arguments.
+% \end{itemize}
+% This system is being used as the basis for \TeX{} programming within
+% The \LaTeX{} Project. Note that the language is not intended for either
+% document mark-up or style specification. Instead, it is intended that
+% such features will be built on top of the conventions described here.
+%
+% This document is an introduction to the ideas behind the \pkg{expl3}
+% programming interface. For the complete documentation of the programming
+% layer provided by The \LaTeX{} Project, see the accompanying
+% \texttt{interface3} document.
+%
+% \end{abstract}
+%
+% \section{Introduction}
+%
+% The first step to develop a \LaTeX{} kernel beyond \LaTeXe{} is to
+% address how the underlying system is programmed.  Rather than the
+% current mix of \LaTeX{} and \TeX{} macros, the \LaTeX3 system provides
+% its own consistent interface to all of the functions needed to
+% control \TeX{}.  A key part of this work is to ensure that everything
+% is documented, so that \LaTeX{} programmers and users can work
+% efficiently without needing to be familiar with the internal nature
+% of the kernel or with plain \TeX{}.
+%
+% The \pkg{expl3} bundle provides this new programming interface for
+% \LaTeX{}. To make programming systematic, \LaTeX3 uses some very
+% different conventions to \LaTeXe{} or plain \TeX{}. As a result,
+% programmers starting with \LaTeX3 need to become familiar with
+% the syntax of the new language.
+%
+% The next section shows where this language fits into a complete
+% \TeX{}-based document processing system.  We then describe the major
+% features of the syntactic structure of command names, including the
+% argument specification syntax used in function names.
+%
+% The practical ideas behind this argument syntax will be explained,
+% together with the expansion control mechanism and the interface
+% used to define variant forms of functions.
+%
+% As we shall demonstrate, the use of a structured naming scheme and of
+% variant forms for functions greatly improves the readability of the
+% code and hence also its reliability.  Moreover, experience has shown
+% that the longer command names which result from the new syntax do not
+% make the process of \emph{writing} code significantly harder.
+%
+% \section{Languages and interfaces}
+%
+% It is possible to identify several distinct languages related to the
+% various interfaces that are needed in a \TeX{}-based document processing
+% system.  This section looks at those we consider most important for
+% the \LaTeX3 system.
+%
+% \begin{description}
+%   \item[Document mark-up] This comprises those commands (often called
+%     tags) that are to embedded in the document (the |.tex| file).
+%
+%     It is generally accepted that such mark-up should be essentially
+%     \emph{declarative}. It may be traditional \TeX{}-based mark-up such
+%      as \LaTeXe{}, as described in~\cite{A-W:LLa94} and~\cite{A-W:GMS94},
+%     or a mark-up language defined via \acro{HTML} or \acro{XML}.
+%
+%     One problem with more traditional \TeX{} coding conventions (as
+%     described in~\cite{A-W:K-TB}) is that the names and syntax of \TeX{}'s
+%     primitive formatting commands are ingeniously designed to be
+%     \enquote{natural} when used directly by the author as document mark-up
+%     or in macros.  Ironically, the ubiquity (and widely recognised
+%     superiority) of logical mark-up has meant that such explicit
+%     formatting commands are almost never needed in documents or in
+%     author-defined macros.  Thus they are used almost exclusively by
+%     \TeX{} programmers to define higher-level commands, and their
+%     idiosyncratic syntax is not at all popular with this community.
+%     Moreover, many of them have names that could be very useful as
+%     document mark-up tags were they not pre-empted as primitives
+%     (\emph{e.g.}~\tn{box} or \tn{special}).
+%
+%   \item[Designer interface] This relates a (human) typographic
+%     designer's specification for a document to a program that
+%     \enquote{formats
+%     the document}.  It should ideally use a declarative language that
+%     facilitates expression of the relationship and spacing rules
+%     specified for the layout of the various document elements.
+%
+%     This language is not embedded in document text and it will be very
+%     different in form to the document mark-up language.  For \LaTeX{},
+%     this level was almost completely missing  from \LaTeX{}2.09; \LaTeXe{}
+%     made some improvements in this area but it is still the case that
+%     implementing a design specification in  \LaTeX{} requires far more
+%     \enquote{low-level} coding than is acceptable.
+%
+%   \item[Programmer interface]
+%     This language is the implementation language within which the
+%     basic typesetting functionality is implemented, building upon the
+%     primitives of \TeX{} (or a  successor program).  It may also be used
+%     to implement the previous two languages \enquote{within} \TeX{}, as in
+%     the
+%     current \LaTeX{} system.
+%
+% \end{description}
+%
+% The last layer is covered by the conventions described in this
+% document, which describes a system aimed at providing a suitable
+% basis for coding \LaTeX3. Its main distinguishing features are
+% summarised here:
+% \begin{itemize}
+%   \item A consistent naming scheme for all commands, including \TeX{}
+%     primitives.
+%   \item The classification of commands as \LaTeX{} functions or \LaTeX{}
+%     parameters, and also their division into modules according to their
+%     functionality.
+%   \item A simple mechanism for controlling argument expansion.
+%   \item Provision of a set of core \LaTeX{} functions that is sufficient
+%     for handling programming constructs such as queues, sets, stacks,
+%     property lists.
+%   \item A \TeX{} programming environment in which, for example, all
+%     white space is ignored.
+% \end{itemize}
+%
+% \section{The naming scheme}
+%
+% \LaTeX3 does not use |@| as a \enquote{letter} for defining
+% internal macros.  Instead, the symbols |_| and |:|
+% are used in internal macro names to provide structure. In
+% contrast to the plain \TeX{} format and the \LaTeXe{} kernel, these
+% extra letters are used only between parts of a macro name (no
+% strange vowel replacement).
+%
+% While \TeX{} is actually a macro processor, by
+% convention for the \pkg{expl3} programming language we distinguish between
+% \emph{functions} and \emph{variables}. Functions can have arguments and they
+% are either expanded or executed.  Variables can be assigned values and they
+% are used in arguments to functions; they are not used directly but are
+% manipulated by functions (including getting and setting functions).
+% Functions and variables with a related functionality (for example accessing
+% counters, or manipulating token lists, \emph{etc.})\ are collected together
+% into a
+% \emph{module}.
+%
+% \subsection{Examples}
+%
+% Before giving the details of the naming scheme, here are a few typical
+% examples to indicate the flavour of the scheme; first some variable
+% names.
+% \begin{quote}
+%   \cs{l_tmpa_box} is a local variable (hence the~|l_| prefix)
+%     corresponding to a box register.\\
+%   \cs{g_tmpa_int} is a global variable (hence the~|g_| prefix)
+%     corresponding to an integer register (i.e.~a \TeX{} count
+%     register).\\
+%   \cs{c_empty_tl} is the constant~(|c_|) token list variable
+%     that is always empty.
+% \end{quote}
+%
+% Now here is an example of a typical function name.
+%
+% \cs{seq_push:Nn} is the function which puts the token list specified
+% by its second argument onto the stack specified by its first argument.
+% The different natures of the two arguments are indicated by the~|:Nn|
+% suffix. The first argument must be a single token which \enquote{names}
+% the stack parameter: such single-token arguments are denoted~|N|.
+% The second argument is a normal \TeX{} \enquote{undelimited argument},
+% which
+% may either be a single token or a balanced, brace-delimited token
+% list (which we shall here call a \textit{braced token list}): the~|n|
+% denotes such a \enquote{normal} argument form. The name of the function
+% indicates it belongs to the |seq| module.
+%
+% \subsection{Formal naming syntax}
+%
+% We shall now look in more detail at the syntax of these names. A
+% function name in \LaTeX3 has a name consisting of three parts:
+% \begin{quote}
+%   |\|\meta{module}|_|\meta{description}|:|\meta{arg-spec}
+% \end{quote}
+% while a variable has (up to) four distinct parts to its name:
+% \begin{quote}
+%   |\|\meta{scope}|_|\meta{module}|_|\meta{description}|_|\meta{type}
+% \end{quote}
+%
+% The syntax of all names contains
+% \begin{quote}
+%   \meta{module} and \meta{description}
+% \end{quote}
+% these both give information about the command.
+%
+% A \emph{module} is a collection of closely related functions and
+% variables. Typical module names include~|int| for integer parameters
+% and related functions,~|seq| for sequences and~|box| for boxes.
+%
+% Packages providing new programming functionality will add new modules
+% as needed; the programmer can choose any unused name, consisting
+% of letters only, for a module. In general, the module name and module
+% prefix should be related: for example, the kernel module containing
+% \texttt{box} functions is called \texttt{l3box}.  Module names and
+% programmers' contact details are listed in \pkg{l3prefixes.csv}.
+%
+% The \emph{description} gives more detailed information about the
+% function or parameter, and provides a unique name for it.  It should
+% consist of letters and, possibly,~|_|~characters. In general, the
+% description should use |_| to divide up \enquote{words} or other easy to
+% follow parts of the name.  For example, the \LaTeX3 kernel provides
+% \cs{if_cs_exist:N} which, as might be expected, tests if a command
+% name exists.
+%
+% Where functions for variable manipulation can perform assignments
+% either locally or globally, the latter case is indicated by the inclusion of
+% a |g| in the second part of the function name. Thus \cs{tl_set:Nn} is a local
+% function but \cs{tl_gset:Nn} acts globally. Functions of this type are
+% always documented together, and the scope of action may therefore be
+% inferred from the presence or absence of a |g|. See the next subsection for
+% more detail on variable scope.
+%
+% \subsubsection{Separating private and public material}
+%
+% One of the issues with the \TeX{} language is that it doesn't support
+% name spaces and encapsulation other than by convention. As a result
+% nearly every internal command in the \LaTeXe{} kernel has eventually
+% be used by extension packages as an entry point for modifications or
+% extensions. The consequences of this is that nowadays it is next to
+% impossible to change anything in the \LaTeXe{} kernel (even if it is
+% clearly just an internal command) without breaking something.
+%
+% In \pkg{expl3} we hope to improve this situation drastically by
+% clearly separating public interfaces (that extension packages can use
+% and rely on) and private functions and variables (that should not
+% appear outside of their module).  There is (nearly) no way to enforce
+% this without severe computing overhead, so we implement it only
+% through a naming convention, and some support mechanisms.  However, we
+% think that this naming convention is easy to understand and to follow,
+% so that we are confident that this will adopted and provides the
+% desired results.
+%
+% Functions created by a module may either be \enquote{public} (documented
+% with a defined interface) or \enquote{private} (to be used only within
+% that module, and thus not formally documented). It is important that
+% only documented interfaces are used; at the same time, it is necessary to
+% show within the name of a function or variable whether it is public
+% or private.
+%
+% To allow clear separation of these two cases, the following convention
+% is used. To denote a private function or a private variable (of the module),
+% two |_| characters are used in front of the module name, e.g.
+% \begin{verbatim}
+%   \module_foo:nnn
+% \end{verbatim}
+% is a public function which should be documented while
+% \begin{verbatim}
+%   \__module_foo:nnn
+% \end{verbatim}
+% is private to the module, and should \emph{not} be used outside of that
+% module.
+%
+% For variables, to avoid three |_| in a row, the separator for the variable
+% scope and any leading |_| for a private interface in the module part are
+% combined. Thus
+% \begin{verbatim}
+%   \l_module_foo_tl
+% \end{verbatim}
+% is a public variable and
+% \begin{verbatim}
+%   \l__module_foo_tl
+% \end{verbatim}
+% is private.
+%
+% \subsubsection{Using \texttt{@@} and \pkg{DocStrip} to mark private code}
+%
+% The formal syntax for internal functions allows clear separation of public
+% and private code, but includes redundant information (every internal function
+% or variable includes \texttt{__\meta{module}}). To aid programmers, the
+% \pkg{DocStrip} program introduces the syntax
+% \begin{quote}
+%   \ttfamily
+%   |%<@@=|\meta{module}|>|
+% \end{quote}
+% which then allows |@@| (and |_@@| in case of variables) to be used as
+% a place holder for \texttt{__\meta{module}} in code. Thus for example
+% \begin{verbatim}
+%   %<@@=foo>
+%   %    \begin{macrocode}
+%   \cs_new:Npn \@@_function:n #1
+%     ...
+%   \tl_new:N \l_@@_my_tl
+%   %    \end{macrocode}
+% \end{verbatim}
+% is converted by \pkg{DocStrip} to
+% \begin{verbatim}
+%   \cs_new:Npn \__foo_function:n #1
+%     ...
+%   \tl_new:N \l__foo_my_tl
+% \end{verbatim}
+% on extraction. As you can see both |_@@| and |@@| are mapped to
+% \texttt{__\meta{module}}, because we think that this helps to
+% distinguish variables from functions in the source when the |@@|
+% convention is used.
+%
+% \subsubsection{Variables: declaration}
+%
+% In well-formed \pkg{expl3} code, variables should always be declared before
+% assignment is attempted. This is true even for variable types where the
+% underlying \TeX{} implementation will allow direct assignment. This applies
+% both to setting directly (\cs{tl_set:Nn}, etc.) and to setting equal
+% (\cs{tl_set_eq:NN}, etc.).
+%
+% To help programmers to adhere to this approach, the debugging option
+% |check-declarations| may be given
+% \begin{verbatim}
+%   \debug_on:n { check-declarations }
+% \end{verbatim}
+% and will issue an error whenever an assignment is made to a non-declared
+% variable. There is a performance implication, so this option should only
+% be used for testing.
+%
+% \subsubsection{Variables: scope and type}
+%
+% The \meta{scope} part of the name describes how the variable can be
+% accessed.  Variables are classified as local, global or constant.
+% This \emph{scope} type appears as a code at the beginning of the name;
+% the codes used are:
+% \begin{arg-description}
+%   \item[c] constants (global variables whose value should not be
+%     changed);
+%   \item[g] variables whose value should only be set globally;
+%   \item[l] variables whose value should only be set locally.
+% \end{arg-description}
+%
+% Separate functions are provided to assign data to local and global
+% variables; for example, \cs{tl_set:Nn} and \cs{tl_gset:Nn} respectively
+% set the value of a local or global \enquote{token list} variable.
+% Note that it is a poor \TeX{} practice to intermix local and global
+% assignments to a variable; otherwise you risk exhausting the save
+% stack.\footnote{See \emph{The \TeX{}book}, p.\,301, for further
+% information.}
+%
+% The \meta{type} is in the list of available
+% \emph{data-types};\footnote{Of course, if a totally new data type is
+% needed then this will not be the case. However, it is hoped that only
+% the kernel team will need to create new data types.} these include the
+% primitive \TeX{} data-types, such as the various registers, but to
+% these are added data-types built within the \LaTeX{} programming
+% system.
+%
+% The data types in \LaTeX3 are:
+% \begin{description}
+%   \item[bitset] a string of bits (\texttt{0} and \texttt{1} tokens) that are
+%                 accessed by position or by name;
+%   \item[bool]   either true or false (the \LaTeX3 implementation does
+%                 not use \tn{iftrue} or \tn{iffalse});
+%   \item[box]    box register;
+%   \item[cctab]  category code table;
+%   \item[clist]  comma separated list;
+%   \item[coffin] a \enquote{box with handles} --- a higher-level data
+%                 type for carrying out |box| alignment operations;
+%   \item[dim]    \enquote{rigid} lengths;
+%   \item[fp]     floating-point values;
+%   \item[fparray] fixed-size vector of floating-point values;
+%   \item[int]    integer-valued count register;
+%   \item[intarray] fixed-size vector of integer values;
+%   \item[ior]    an input stream (for reading from a file);
+%   \item[iow]    an output stream (for writing to a file);
+%   \item[muskip] math mode \enquote{rubber} lengths;
+%   \item[prop]   property list;
+%   \item[regex]  regular expression;
+%   \item[seq]    sequence: a data-type used to implement lists (with
+%                 access at both ends) and stacks;
+%   \item[skip]   \enquote{rubber} lengths;
+%   \item[str]    \TeX{} strings: a special case of |tl| in which all
+%                 characters have category \enquote{other} (catcode~$12$),
+%                 other than spaces which are category \enquote{space}
+%                 (catcode~$10$);
+%   \item[token]  equal to a single arbitrary token;
+%   \item[tl]     \enquote{token list variables}: placeholders for token lists.
+% \end{description}
+% When the \meta{type} and \meta{module} are identical (as often happens in
+% the more basic modules) the \meta{module} part is often omitted for
+% aesthetic reasons.
+%
+% The name \enquote{token list} may cause confusion, and so some
+% background is useful.  \TeX{} works with tokens and lists of tokens,
+% rather than characters. It provides two ways to store these token
+% lists: within macros and as token registers (|toks|). The
+% implementation in \LaTeX3 means that |toks| are not required, and that
+% all operations for storing tokens can use the |tl| variable type.
+%
+% Experienced \TeX{} programmers will notice that some of the variable
+% types listed are native \TeX{} registers whilst others are not. In
+% general, the underlying \TeX{} implementation for a data structure may
+% vary but the \emph{documented interface} will be stable. For example,
+% the |prop| data type was originally implemented as a |toks|, but
+% is currently built on top of the |tl| data structure.
+%
+% \subsubsection{Variables: guidance}
+%
+% Both comma lists and sequences have similar characteristics.
+% They both use special delimiters to mark out one entry from the
+% next, and are both accessible at both ends. In general, it is
+% easier to create comma lists `by hand' as they can be typed
+% in directly. User input often takes the form of a comma separated
+% list and so there are many cases where this is the obvious
+% data type to use. On the other hand, sequences use special internal
+% tokens to separate entries. This means that they can be used to
+% contain material that comma lists cannot (such as items that may
+% themselves contain commas!). In general, comma lists should be
+% preferred for creating fixed lists inside programs and for
+% handling user input where commas will not occur. On the other
+% hand, sequences should be used to store arbitrary lists of
+% data.
+%
+% \pkg{expl3} implements stacks using the sequence data structure.
+% Thus creating stacks involves first creating a sequence, and
+% then using the sequence functions which work in a stack manner
+% (\cs{seq_push:Nn}, \emph{etc}.).
+%
+% Due to the nature of the underlying \TeX{} implementation, it is
+% possible to assign values to token list variables and comma lists
+% without first declaring them. However, this is \emph{not supported
+% behavior}. The \LaTeX3 coding convention is that all variables must
+% be declared before use.
+%
+% The \pkg{expl3} package can be loaded with the \texttt{check-declarations}
+% option to verify that all variables are declared before use. This has
+% a performance implication and is therefore intended for testing during
+% development and not for use in production documents.
+%
+% \subsubsection{Functions: argument specifications}
+%
+% Function names end with an \meta{arg-spec} after a colon.  This
+% gives an indication of the types of argument that a function takes,
+% and provides a convenient method of naming similar functions that
+% differ only in their argument forms (see the next section for
+% examples).
+%
+% The \meta{arg-spec} consists of a (possibly empty) list of letters,
+% each denoting one argument of the function. The letter, including
+% its case, conveys information about the type of argument required.
+%
+% All functions have a base form with arguments using one of the
+% following argument specifiers:
+% \begin{arg-description}
+%   \item[n]  Unexpanded token or braced token list.\\
+%     This is a standard \TeX{} undelimited macro argument.
+%   \item[N]  Single token (unlike~|n|, the argument must \emph{not} be
+%     surrounded by braces).\\
+%     A typical example of a command taking an~|N|
+%     argument is~|\cs_set|, in which the command being defined must be
+%     unbraced.
+%   \item[p]  Primitive \TeX{} parameter specification.\\
+%     This can be something simple like~|#1#2#3|, but may use arbitrary
+%     delimited argument syntax such as: |#1,#2\q_stop#3|. This is used
+%     when defining functions.
+%   \item[T,F]
+%     These are special cases of~|n| arguments, used for the
+%     true and false code in conditional commands.
+% \end{arg-description}
+% There are two other specifiers with more general meanings:
+% \begin{arg-description}
+%   \item[D] Stands for \textbf{Do not use}.  This special case is used
+%     for \TeX{} primitives.  These functions have no standardized
+%     syntax, they are engine dependent and their name can change
+%     without warning, thus their use is \emph{strongly discouraged} in
+%     package code: programmers should instead use the interfaces
+%     documented in \href{interface3.pdf}{interface3.pdf}%^^A
+%     \footnote{If a primitive offers a functionality not yet in the
+%       kernel, programmers and users are encouraged to write to the
+%       \texttt{LaTeX-L} mailing list
+%       (\url{mailto:LATEX-L at listserv.uni-heidelberg.de}) describing
+%       their use-case and intended behaviour, so that a possible
+%       interface can be discussed.  Temporarily, while an interface is
+%       not provided, programmers may use the procedure described in the
+%       \href{l3styleguide.pdf}{l3styleguide.pdf}.}.
+%   \item[w] This means that the argument syntax is \enquote{weird} in that it
+%     does not follow any standard rule.  It is used for functions with
+%     arguments that take non standard forms: examples are \TeX{}-level
+%     delimited arguments and the boolean tests needed after certain
+%     primitive |\if|\ldots{} commands.
+% \end{arg-description}
+%
+% In case of |n| arguments that consist of a single token the
+% surrounding braces can be omitted in nearly all
+% situations---functions that force the use of braces even for single
+% token arguments are explicitly mentioned. However, programmers are
+% encouraged to always use braces around \texttt{n} arguments, as this
+% makes the relationship between function and argument clearer.
+%
+% Further argument specifiers are available as part of the expansion
+% control system.  These are discussed in the next section.
+%
+% \section{Expansion control}
+%
+% Let's take a look at some typical operations one might want to
+% perform. Suppose we maintain a stack of open files and we use the
+% stack |\g_ior_file_name_seq| to keep track of them (\texttt{ior} is
+% the prefix used for the file reading module). The basic operation here
+% is to push a name onto this stack which could be done by the operation
+% \begin{quote}
+%   \cs{seq_gpush:Nn} |\g_ior_file_name_seq {#1}|
+% \end{quote}
+% where |#1| is the filename. In other words, this operation would
+% push the file name as is onto the stack.
+%
+% However, we might face a situation where the filename is stored in
+% a variable of some sort, say |\l_ior_curr_file_tl|. In this case we
+% want to retrieve the value of the variable. If we simply use
+% \begin{quote}
+%   \cs{seq_gpush:Nn} |\g_ior_file_name_seq| |\l_ior_curr_file_tl|
+% \end{quote}
+% we do not get the value of the variable pushed onto the stack,
+% only the variable name itself. Instead a suitable number of
+% \cs{exp_after:wN} would be necessary (together with extra braces) to
+% change the order of expansion,\footnote{\cs{exp_after:wN} is
+% the \LaTeX3 name for the \TeX{} \tn{expandafter} primitive.} \emph{i.e.}
+% \begin{quote}
+%   \cs{exp_after:wN}                              \\
+%   |   |\cs{seq_gpush:Nn}                         \\
+%   \cs{exp_after:wN}                              \\
+%   |   \g_ior_file_name_seq|                      \\
+%   \cs{exp_after:wN}                              \\
+%   |   { \l_ior_curr_file_tl }|
+% \end{quote}
+%
+% The above example is probably the simplest case but already shows
+% how the code changes to something difficult to understand.
+% Furthermore there is an assumption in this: that the storage bin
+% reveals its contents after exactly one expansion. Relying on this
+% means that you cannot do proper checking plus you have to know
+% exactly how a storage bin acts in order to get the correct number
+% of expansions.  Therefore \LaTeX3 provides the programmer with a
+% general scheme that keeps the code compact and easy to understand.
+%
+% To denote that some argument to a function needs special treatment one
+% just uses different letters in the arg-spec part of the function to
+% mark the desired behavior. In the above example one would write
+% \begin{quote}
+%   \cs{seq_gpush:NV} |\g_ior_file_name_seq \l_ior_curr_file_tl|
+% \end{quote}
+% to achieve the desired effect. Here the |V| (the second argument)
+% is for \enquote{retrieve the value of the variable} before passing it to
+% the base function.
+%
+% The following letters can be used to denote special treatment of
+% arguments before passing it to the base function:
+% \begin{description}
+%   \item[c] Character string used as a command name.\\ The argument (a
+%     token or braced token list) is \emph{fully expanded}; the result
+%     must be a sequence of characters which is then used to construct a
+%     command name (\emph{via}~\tn{csname} \ldots \tn{endcsname}).  This
+%     command name is a single token that is passed to the function as
+%     the argument. Hence
+%     \begin{quote}
+%       \cs{seq_gpush:cV} |{ g_file_name_seq }| \cs{l_tmpa_tl}
+%     \end{quote}
+%     is equivalent to
+%     \begin{quote}
+%       \cs{seq_gpush:NV} |\g_file_name_seq| \cs{l_tmpa_tl}.
+%     \end{quote}
+%     Full expansion means that (a) the entire
+%     argument must be expandable and (b) any variables are
+%     converted to their content. So the preceding examples are also
+%     equivalent to
+%     \begin{quote}
+%       \cs{tl_new:N} |\g_file_seq_name_tl| \\
+%       \cs{tl_gset:Nn} |\g_file_seq_name_tl { g_file_name_seq }| \\
+%       \cs{seq_gpush:cV} |{| \cs{tl_use:N} |\g_file_seq_name_tl }| \cs{l_tmpa_tl}.
+%     \end{quote}
+%     (Token list variables are expandable and we could omit the
+%     accessor function \cs{tl_use:N}.  Other variable types require the
+%     appropriate \cs{\meta{var}_use:N} functions to be used in this
+%     context.)
+%   \item[V]  Value of a variable.\\
+%     This means that the contents of the register in question is used
+%     as the argument, be it an integer, a length-type register, a token
+%     list variable or similar. The value is passed to the function as a
+%     braced token list.  Can be applied to variables which have a
+%     \cs{\meta{var}_use:N} function (other than boxes),
+%     and which therefore deliver a single \enquote{value}.
+%   \item[v] Value of a register, constructed from a character string
+%     used as a command name.\\
+%     This is a combination of |c| and |V| which first constructs a
+%     control sequence from the argument and then passes the value of
+%     the resulting register to the function.  Can be applied to
+%     variables which have a \cs{\meta{var}_use:N} function (other than
+%     boxes), and which therefore deliver a single
+%     \enquote{value}.
+%   \item[e]  Fully-expanded token or braced token list.\\
+%     This means that the argument is expanded as in the replacement
+%     text of a~\tn{message}, and the expansion is passed to the function as
+%     a braced token list.
+%   \item[o]  One-level-expanded token or braced token list.\\
+%     This means that the argument is expanded one level, as by
+%     \tn{expandafter}, and the expansion is passed to the function as a
+%     braced token list.  Note that if the original argument is a braced
+%     token list then only the first token in that list is expanded.
+%     In general, using \texttt{V} should be preferred to using
+%     \texttt{o} for simple variable retrieval.
+%   \item[f] Expanding the first token recursively in a braced token
+%     list.\\ Almost the same as the |e| type except here the token list
+%     is expanded fully until the first unexpandable token is found and
+%     the rest is left unchanged. Note that if this function finds a
+%     space at the beginning of the argument it gobbles it and does not
+%     expand the next token.
+%   \item[x]  Fully-expanded token or braced token list.\\
+%     This expansion is very similar to |e|-type but is not nestable,
+%     can only be used to create non-expandable functions, and requires
+%     that |#| tokens are doubled in the argument. In almost all cases,
+%     |e|-type should be preferred: retained largely for historical
+%     reasons, and should where possible be replaced by the |e|-type
+%     equivalent.
+% \end{description}
+%
+% \subsection{Simpler means better}
+%
+% Anyone who programs in \TeX{} is frustratingly familiar with the
+% problem of arranging that arguments to functions are suitably expanded
+% before the function is called.  To illustrate how expansion control
+% can bring instant relief to this problem we shall consider two
+% examples copied from \texttt{latex.ltx}.
+%
+% \begin{verbatim}
+%        \global\expandafter\let
+%              \csname\cf at encoding \string#1\expandafter\endcsname
+%              \csname ?\string#1\endcsname
+% \end{verbatim}
+% This first piece of code is in essence simply a global \tn{let} whose
+% two arguments firstly have to be constructed before \tn{let} is
+% executed. The |#1| is a control sequence name such as
+% |\textcurrency|. The token to be defined is obtained by
+% concatenating the characters of the current font encoding stored in
+% |\cf at encoding|, which has to be fully expanded, and the name of the
+% symbol. The second token is the same except it uses the default
+% encoding |?|. The result is a mess of interwoven \tn{expandafter}
+% and \tn{csname} beloved of all \TeX{} programmers, and the code is
+% essentially unreadable.
+%
+% Using the conventions and functionality outlined here, the task would
+% be achieved with code such as this:
+% \begin{verbatim}
+%   \cs_gset_eq:cc
+%     { \cf at encoding \token_to_str:N  #1 } { ? \token_to_str:N #1 }
+% \end{verbatim}
+% The command \cs{cs_gset_eq:cc} is a global~\tn{let} that generates
+% command names out of both of its arguments before making the
+% definition. This produces code that is far more readable and more
+% likely to be correct first time. (\cs{token_to_str:N} is the \LaTeX3
+% name for \tn{string}.)
+%
+% Here is the second example.
+% \begin{verbatim}
+%   \expandafter
+%     \in@
+%   \csname sym#3%
+%     \expandafter
+%       \endcsname
+%     \expandafter
+%       {%
+%     \group at list}%
+% \end{verbatim}
+% This piece of code is part of the definition of another function. It
+% first produces two things: a token list, by expanding |\group at list| once;
+% and a token whose name comes from~`|sym#3|'.  Then the function~\cs{in@}
+% is called and this tests if its first argument occurs in the token list
+% of its second argument.
+%
+% Again we can improve enormously on the code.  First we shall rename
+% the function~\cs{in@}, which tests if its first argument appears
+% within its second argument, according to our conventions.  Such a
+% function takes two normal \enquote{\texttt{n}} arguments and operates
+% on token lists: it might reasonably be named |\tl_test_in:nn|.  Thus
+% the variant function we need would be defined with the appropriate
+% argument types and its name would be |\tl_test_in:cV|.  Now this code
+% fragment would be simply:
+% \begin{verbatim}
+%   \tl_test_in:cV { sym #3 } \group at list
+% \end{verbatim}
+% This code could be improved further by using a sequence |\l_group_seq|
+% rather than the bare token list |\group at list|.  Note that, in addition
+% to the lack of \tn{expandafter}, the space after the~|}| is
+% silently ignored since all white space is ignored in this programming
+% environment.
+%
+% \subsection{New functions from old}
+%
+% For many common functions the \LaTeX3 kernel provides variants
+% with a range of argument forms, and similarly it is expected that
+% extension packages providing new functions will make them available in
+% all the commonly needed forms.
+%
+% However, there will be occasions where it is necessary to construct a
+% new such variant form; therefore the expansion module provides a
+% straightforward mechanism for the creation of functions with any
+% required argument type, starting from a function that takes \enquote{normal}
+% \TeX{} undelimited arguments.
+%
+% To illustrate this let us suppose you have a \enquote{base function}
+% |\demo_cmd:Nnn| that takes three normal arguments, and that you need
+% to construct the variant |\demo_cmd:cne|, for which the first argument
+% is used to construct the \emph{name} of a command, whilst the third
+% argument must be fully expanded before being passed to
+% |\demo_cmd:Nnn|.
+% To produce the variant form from the base form, simply use this:
+% \begin{verbatim}
+%   \cs_generate_variant:Nn \demo_cmd:Nnn { cne }
+% \end{verbatim}
+% This defines the variant form so that you can then write, for example:
+% \begin{verbatim}
+%   \demo_cmd:cne { abc } { pq } { \rst \xyz }
+% \end{verbatim}
+% rather than \ldots\ well, something like this!
+% \begin{verbatim}
+%   \def \tempa {{pq}}%
+%   \edef \tempb {\rst \xyz}%
+%   \expandafter
+%     \demo at cmd:nnn
+%   \csname abc%
+%     \expandafter
+%       \expandafter
+%     \expandafter
+%         \endcsname
+%     \expandafter
+%       \tempa
+%     \expandafter
+%       {%
+%     \tempb
+%       }%
+% \end{verbatim}
+%
+% Another example: you may wish to declare a function
+% |\demo_cmd_b:enene|, a variant of an existing function
+% |\demo_cmd_b:nnnnn|, that fully
+% expands arguments 1,~3 and~5, and produces commands to pass as
+% arguments 2 and~4 using~\tn{csname}.
+% The definition you need is simply
+% \begin{verbatim}
+%   \cs_generate_variant:Nn \demo_cmd_b:nnnnn { enene }
+% \end{verbatim}
+%
+% This extension mechanism is written so that if the same new form of
+% some existing command is implemented by two extension packages then the
+% two definitions are identical and thus no conflict occurs.
+%
+% \section{The distribution}
+%
+% The \pkg{expl3} modules are designed to be loaded on top of \LaTeXe{}.
+%
+% \begin{bfseries}
+%   The core \pkg{expl3} language is broadly stable, and thus
+%   the syntax conventions and functions provided
+%   are now ready for wider use. There may still be changes to some
+%   functions, but these will be minor when compared to the scope of
+%   \pkg{expl3}. A robust mechanism is in place for such deprecations.
+% \end{bfseries}
+%
+% The distribution of \pkg{expl3} is split up into three packages on
+% CTAN: \pkg{l3kernel}, \pkg{l3packages} and \pkg{l3experimental}.
+% The core programming layer provided by \pkg{l3kernel} has been loaded
+% as part of the \LaTeX{} since 2020-02-02. For historical reasons, in
+% older kernel releases
+% \begin{verbatim}
+%   \RequirePackage{expl3}
+% \end{verbatim}
+% loads the code distributed as \pkg{l3kernel}. This monolithic
+% package contains all of the modules regarded by the team as stable,
+% and any changes in this code are very limited. This material is
+% therefore suitable for use in third-party packages without concern
+% about changes in support. All of this code is documented in
+% \texttt{interface3.pdf}.
+%
+% The material in \pkg{l3packages} is also stable; this bundle provides
+% user-level commands, some of which have been integrated in the
+% \LaTeX{} kernel.
+%
+% Finally, \pkg{l3experimental} contains modules ready for public use
+% but not yet integrated into \pkg{l3kernel}. These modules have to
+% be loaded explicitly. The team anticipate that all of these modules
+% will move to stable status over time, but they may be more flexible
+% in terms of interface and functionality detail. Feedback on these
+% modules is extremely valuable.
+%
+% \section{Moving from \LaTeXe{} to \pkg{expl3}}
+%
+% To help programmers to use \pkg{expl3} code in existing \LaTeXe{} package,
+% some short notes on making the change are probably desirable.
+% Suggestions for inclusion here are welcome! Some of the following
+% is concerned with code, and some with coding style.
+%
+% \begin{itemize}
+%   \item \pkg{expl3} is mainly focused on programming. This means that
+%     some areas still require the use of \LaTeXe{} internal macros.
+%     For example, you may well need \tn{IfPackageLoadedTF}, as there
+%     is currently no native \pkg{expl3} package loading module.
+%   \item User level macros should be generated using the mechanism
+%     available in the \pkg{ltcmd} module, which is part of the
+%     the \LaTeX{} kernel since 2020-10-01.
+%   \item At an internal level, most functions should be generated
+%     \tn{long} (using \cs{cs_new:Npn}) rather than \enquote{short} (using
+%     \cs{cs_new_nopar:Npn}).
+%   \item Where possible, declare all variables and functions (using
+%     \cs{cs_new:Npn}, \cs{tl_new:N}, etc.) before use.
+%   \item Prefer \enquote{higher-level} functions over \enquote{lower-level},
+%     where possible. So for example use \cs{cs_if_exist:NTF} and not
+%     \cs{if_cs_exist:N}.
+%   \item Use space to make code readable. In general, we recommend
+%     a layout such as:
+%     \begin{verbatim}
+%       \cs_new:Npn \foo_bar:Nn #1#2
+%         {
+%           \cs_if_exist:NTF #1
+%             { \__foo_bar:n {#2} }
+%             { \__foo_bar:nn {#2} { literal } }
+%         }
+%     \end{verbatim}
+%     where spaces are used around |{| and |}| except for isolated
+%     |#1|, |#2|, \emph{etc.}
+%   \item Put different code items on separate lines: readability is
+%     much more useful than compactness.
+%   \item Use long, descriptive names for functions and variables,
+%     and for auxiliary functions use the parent function name plus
+%     |aux|, |auxi|, |auxii| and so on.
+%   \item If in doubt, ask the team via the LaTeX-L list: someone will
+%     soon get back to you!
+% \end{itemize}
+%
+% \section{Load-time options for \pkg{expl3}}
+%
+% To support code authors, the \pkg{expl3} package for \LaTeXe{} includes
+% a small number of load-time options. These all work in a key--value
+% sense, recognising the \texttt{true} and \texttt{false} values. Giving
+% the option name alone is equivalent to using the option with the
+% \texttt{true} value.
+%
+% \DescribeOption{check-declarations}
+% All variables used in \pkg{expl3} code should be declared. This is enforced
+% by \TeX{} for variable types based on \TeX{} registers, but not for those
+% which are constructed using macros as the underlying storage system. The
+% \texttt{check-declarations} option enables checking for all variable
+% assignments, issuing an error if any variables are assigned without being
+% initialised.  See also \cs{debug_on:n} \texttt{\{check-declarations\}}
+% in \pkg{interface3} for finer control.
+%
+% \DescribeOption{log-functions}
+% The \texttt{log-functions} option is used to enable recording of every new
+% function name in the \texttt{.log} file. This is useful for debugging
+% purposes, as it means that there is a complete list of all functions
+% created by each module loaded (with the exceptions of a very small number
+% required by the bootstrap code).  See also \cs{debug_on:n}
+% \texttt{\{log-functions\}} in \pkg{interface3} for finer control.
+%
+% \DescribeOption{backend}
+% Selects the backend to be used for color, graphics and related operations that
+% are backend-dependent. Options available are
+% \begin{itemize}[font = \texttt]
+%   \item[dvips] Use the \texttt{dvips} driver.
+%   \item[dvipdfmx] Use the \texttt{dvipdfmx} driver.
+%   \item[dvisvgm] Use the \texttt{dvisvgm} driver.
+%   \item[luatex] Use the direct PDF output mode of \LuaTeX{}
+%   \item[pdftex] Use the direct PDF output mode of \pdfTeX{}
+%   \item[xetex] Use the \XeTeX{} version of the \texttt{dvipdfmx} driver.
+% \end{itemize}
+% For historical reasons, there is also \texttt{pdfmode} as an equivalent of
+% \texttt{luatex} or \texttt{pdftex}, and \texttt{xdvipdfmx} as
+% an equivalent to \texttt{xetex}, but these are deprecated
+%
+% \DescribeOption{suppress-backend-headers}
+% The \texttt{suppress-backend-headers} option suppresses loading of
+% backend-specific header files; currently this only affects \texttt{dvips}.
+% This option is available to support DVI-based routes that do not
+% support the |header| line used by \texttt{dvips}.
+%
+% The debugging options may also be given using
+% \verb|\keys_set:nn { sys } { ... }|; the \texttt{backend} option can be
+% given in this way \emph{only} if a backend has not already been loaded.
+% This method of setting options is useful where \pkg{expl3} is pre-loaded
+% by the \LaTeXe{} format.
+%
+% \section{Using \pkg{expl3} with formats other than \LaTeXe{}}
+%
+% As well as the \LaTeXe{} package \pkg{expl3}, there is also a
+% \enquote{generic} loader for the code, \texttt{expl3-generic.tex}.
+% This may be loaded using the plain \TeX{} syntax
+% \begin{verbatim}
+%   \input expl3-generic %
+% \end{verbatim}
+% This enables the programming layer to work with the other formats.
+% As no options are available loading in this way, the \enquote{native}
+% drivers are automatically used. If this \enquote{generic} loader is
+% used with \LaTeXe{} the code automatically switches to the appropriate
+% package route.
+%
+% After loading the programming layer using the generic interface, the
+% commands \cs{ExplSyntaxOn} and \cs{ExplSyntaxOff} and the code-level
+% functions and variables detailed in \pkg{interface3} are available.
+% Note that other \LaTeXe{} packages \emph{using} \pkg{expl3} are not
+% loadable: package loading is dependent on the \LaTeXe{} package-management
+% mechanism.
+%
+% \section{Getting the version of \pkg{expl3}}
+%
+% \begin{function}{\ExplLoaderFileDate}
+%   Once the programming layer is loaded by one of the loaders, you can access
+%   its version in the ISO date format \meta{year}-\meta{month}-\meta{day},
+%   through \cs{ExplLoaderFileDate}.
+%
+%   The current version of \pkg{expl3} is \ExplLoaderFileDate.
+% \end{function}
+%
+% \section{Engine/primitive requirements}
+%
+% To use \pkg{expl3} and the higher level packages provided by the
+% team, the minimal set of primitive requirements is currently described
+% in \href{README.md}{README.md}.
+%
+% Practically, these requirements are met by the engines
+% \begin{itemize}
+%    \item \pdfTeX{} v1.40.20 or later.
+%    \item \XeTeX{} v0.999991 or later.
+%    \item \LuaTeX{} v1.10 or later.
+%    \item e-(u)\pTeX{} v3.8.2 or later.
+%    \item Prote (2021) or later.
+% \end{itemize}
+%
+% Additional modules beyond the core of \pkg{expl3} may require additional
+% primitives. In particular, third-party authors may significantly
+% extend the primitive coverage requirements.
+%
+% \section{The \LaTeX{} Project}
+%
+% Development of \LaTeX3 is carried out by The \LaTeX{} Project:
+% \url{https://www.latex-project.org/latex3/}.
+%
+% \begin{thebibliography}{1}
+%
+%   \bibitem{A-W:K-TB}
+%     Donald E Knuth
+%     \newblock \emph{The \TeX{}book}.
+%     \newblock Addison-Wesley, Reading, Massachusetts, 1984.
+%
+%   \bibitem{A-W:GMS94}
+%     Goossens, Mittelbach and Samarin.
+%     \newblock \emph{ The \LaTeX{} Companion}.
+%     \newblock Addison-Wesley, Reading, Massachusetts, 1994.
+%
+%   \bibitem{A-W:LLa94}
+%     Leslie Lamport.
+%     \newblock \emph{\LaTeX{}: A Document Preparation System}.
+%     \newblock Addison-Wesley, Reading, Massachusetts, second edition, 1994.
+%
+%   \bibitem{tub:MR97-1}
+%     Frank Mittelbach and Chris Rowley.
+%     \newblock \enquote{The \LaTeX{} Project}.
+%     \newblock \emph{TUGboat},
+%     Vol.\,18, No.\,3, pp.\,195--198, 1997.
+%
+% \end{thebibliography}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{expl3} implementation}
+%
+% The implementation here covers several things. There are two
+% \enquote{loaders} to define: the parts of the code that are specific to
+% \LaTeXe{} or to non-\LaTeXe{} formats. These have to cover the same
+% concepts as each other but in rather different ways: as a result, much
+% of the code is given in separate blocks. There is also a short piece of
+% code for the start of the \enquote{payload}: this is to ensure that
+% loading is always done in the right way.
+%
+% \subsection{Loader interlock}
+%
+% A short piece of set up to check that the loader and \enquote{payload}
+% versions match.
+%
+% \begin{macro}{\ExplLoaderFileDate}
+%   As DocStrip is used to generate \cs{ExplFileDate}
+%   for all files from the same source, it has to match. Thus the loaders
+%   simply save this information with a new name.
+%    \begin{macrocode}
+%<*loader>
+\let\ExplLoaderFileDate\ExplFileDate
+%</loader>
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\c__kernel_expl_date_tl}
+%   The \LaTeXe{} loader stores a private copy of \cs{ExplFileDate},
+%   which is fixed when the format is build and cannot be changed later.
+%   While \cs{ExplFileDate} ensures that the loader (either
+%   \texttt{2ekernel} or \texttt{package}) version matches the version
+%   of \file{expl3-code.tex}, this one ensures that the version of an
+%   eventual |\usepackage{expl3}| matches the version from the format.
+%   It seems to be common to have stray format files in the user tree
+%   which trigger errors due to mismatched versions (\emph{e.g.}
+%   \url{https://github.com/latex3/latex3/issues/781}).
+%
+%   This block also goes to the generic loader, as \pkg{expl3} isn't
+%   preloaded there, so the kernel date should be equal to the loader
+%   date.
+%    \begin{macrocode}
+%<*2ekernel|generic>
+\begingroup
+  \catcode`\_=11
+  \expandafter
+  \ifx\csname c__kernel_expl_date_tl\endcsname\relax
+    \global\let\c__kernel_expl_date_tl\ExplFileDate
+  \fi
+\endgroup
+%</2ekernel|generic>
+%    \end{macrocode}
+% \end{macro}
+%
+% The interlock test itself is simple: \cs{ExplLoaderFileDate} must be
+% defined and identical to \cs{ExplFileDate}. As this has to work for
+% both \LaTeXe{} and other formats, there is some auto-detection involved.
+% (Done this way avoids having two very similar blocks for \LaTeXe{} and
+% other formats.)
+%    \begin{macrocode}
+%<*!loader>
+\begingroup
+  \def\next{\endgroup}%
+  \expandafter\ifx\csname PackageError\endcsname\relax
+    \begingroup
+      \def\next{\endgroup\endgroup}%
+      \def\PackageError#1#2#3%
+        {%
+          \endgroup
+          \errhelp{#3}%
+          \errmessage{#1 Error: #2!}%
+        }%
+  \fi
+  \expandafter\ifx\csname ExplLoaderFileDate\endcsname\relax
+    \def\next
+      {%
+        \PackageError{expl3}{No expl3 loader detected}
+          {%
+            You have attempted to use the expl3 code directly rather than using
+            the correct loader. Loading of expl3 will abort.
+          }%
+        \endgroup
+        \endinput
+      }
+  \else
+    \ifx\ExplLoaderFileDate\ExplFileDate
+    \else
+      \def\next
+        {%
+          \PackageError{expl3}{Mismatched expl3 files detected}
+            {%
+              You have attempted to load expl3 with mismatched files:
+              probably you have one or more files 'locally installed' which
+              are in conflict. Loading of expl3 will abort.
+            }%
+          \endgroup
+          \endinput
+        }%
+    \fi
+\fi
+\next
+%</!loader>
+%    \end{macrocode}
+%
+% A reload test for the payload, just in case.
+%    \begin{macrocode}
+%<*!loader>
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname ver at expl3-code.tex\endcsname\relax
+  \expandafter\edef\csname ver at expl3-code.tex\endcsname
+    {%
+      \ExplFileDate\space
+      L3 programming layer
+    }%
+\else
+  \expandafter\endinput
+\fi
+%</!loader>
+%    \end{macrocode}
+%
+% All good: log the version of the code used (for log completeness). As this
+% is more-or-less \cs{ProvidesPackage} without a separate file and as this also
+% needs to work without \LaTeXe{}, just write the information directly to the
+% log.
+%    \begin{macrocode}
+%<*!loader>
+\immediate\write-1 %
+  {%
+    Package: expl3
+      \ExplFileDate\space
+      L3 programming layer (code)%
+  }%
+%</!loader>
+%    \end{macrocode}
+%
+% \subsection{\LaTeXe{} loaders}
+%
+% Loading with \LaTeXe{} may be as part of the format (pre-loading)
+% or as a package. We have to allow for both possible paths, and of
+% course the package being loaded on to of the pre-load. That means
+% the code here must be safe against re-loading.
+%
+%    \begin{macrocode}
+%<*package&loader|2ekernel>
+%    \end{macrocode}
+%
+% Identify the package or add to the format message.
+%    \begin{macrocode}
+%<*2ekernel>
+\ifdefined\LaTeXReleaseInfo
+  \LaTeXReleaseInfo\expandafter{\the\LaTeXReleaseInfo
+    \show at release@info{L3 programming layer <\ExplFileDate>}%
+  }%
+\else
+  \everyjob\expandafter{\the\everyjob
+    \message{L3 programming layer <\ExplFileDate>}%
+  }%
+\fi
+%</2ekernel>
+%<*!2ekernel>
+\ProvidesPackage{expl3}
+  [%
+    \ExplFileDate\space
+    L3 programming layer (loader)
+  ]%
+%</!2ekernel>
+%    \end{macrocode}
+%
+% \begin{macro}{\ProvidesExplPackage, \ProvidesExplClass, \ProvidesExplFile}
+%   For other packages and classes building on this one it is convenient
+%   not to need \cs{ExplSyntaxOn} each time.  All macros use the same
+%   internal one with the proper \LaTeXe{} command.
+%    \begin{macrocode}
+\protected\def\ProvidesExplPackage
+  {\@expl at provides@file@@Nnnnnn\ProvidesPackage{Package}}
+\protected\def\ProvidesExplClass
+  {\@expl at provides@file@@Nnnnnn\ProvidesClass{Document Class}}
+\protected\def\ProvidesExplFile
+  {\@expl at provides@file@@Nnnnnn\ProvidesFile{File}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@expl at provides@file@@Nnnnnn}
+% \begin{macro}{\@expl at provides@file@@N}
+% \begin{macro}{\@expl at provides@generic@@wnnw}
+%   We need to check the existence of the
+%   \cs[no-index]{Provides\meta{thing}}, since we need to load this very
+%   early in the \LaTeXe{} kernel. The gymnastics with the version identifier
+%   argument allow for the case where it starts with a \texttt{v} and the one
+%   where it does not: formally the \texttt{v} is not part of the version,
+%   but a lot of people include it.
+%    \begin{macrocode}
+\protected\long\def\@expl at provides@file@@Nnnnnn#1#2#3#4#5#6%
+  {%
+    \ifnum0%
+        \ifdefined#11\fi
+        \ifx\relax#1\else1\fi
+        =11
+      \expandafter#1%
+    \else
+      \@expl at provides@generic@@wnnw{#2}%
+    \fi
+      {#3}[{#4 \ifx\relax#5\relax\else\@expl at provides@file@@N#5\space\fi #6}]%
+    \ExplSyntaxOn
+  }
+\long\def\@expl at provides@file@@N#1{v\if#1v\else#1\fi}
+\protected\long\def\@expl at provides@generic@@wnnw#1\fi#2[#3]%
+  {%
+    \immediate\write-1{#1: #2 #3}%
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%  Load the business end: this leaves \cs{expl3} syntax on.
+%  The test ensures we only load once without needing to know if
+%  there was a preloading step.
+%    \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname tex\string _let:D\endcsname\relax
+  \expandafter\@firstofone
+\else
+  \expandafter\@gobble
+\fi
+  {\input expl3-code.tex }%
+%    \end{macrocode}
+%
+% A check that the bootstrap code did not abort loading: if it did,
+% bail out silently here.
+%    \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname tex\string _let:D\endcsname\relax
+  \expandafter\endinput
+\fi
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=expl>
+%    \end{macrocode}
+%
+% At this point, if we have \cs{c__kernel_expl_date_tl} defined, just
+% call the \cs{__kernel_dependency_version_check:Nn} auxiliary to check
+% if it matches \cs{ExplLoaderFileDate}.  Here the test is performed
+% only if \cs{c__kernel_expl_date_tl} exists because this file can be
+% loaded in a \LaTeXe{} format without \pkg{expl3} preloaded, where that
+% token list doesn't exist.
+%
+% This is all done in the \texttt{package} \pkg{docstrip} guard because
+% it doesn't apply to \pkg{expl3.ltx}.
+%    \begin{macrocode}
+%<*package>
+\ifcsname\detokenize{c__kernel_expl_date_tl}\endcsname
+  \expandafter\@firstofone
+\else
+%    \end{macrocode}
+% If \cs{c__kernel_expl_date_tl} does \emph{not} exist we may be loading
+% in a format without \pkg{expl3} preloaded or in the earlier (although
+% still compatible) version in which the error mentioned above showed
+% up.  If loading as a package, \file{expl3-code.tex} got read and here
+% the \pkg{expl3} syntax is on.  Otherwise it was already loaded in a
+% sligtly older kernel, so we fire the incompatibility error message and
+% abort loading.
+%    \begin{macrocode}
+  \ifodd\csname\detokenize{l__kernel_expl_bool}\endcsname
+%    \end{macrocode}
+%   In package mode all files are loaded in one go, so versions will
+%   match.  We just have to set \cs{c__kernel_expl_date_tl} so that
+%   further dependencies don't break:
+%    \begin{macrocode}
+    \global\expandafter\let\csname\detokenize
+      {c__kernel_expl_date_tl}\endcsname\ExplLoaderFileDate
+    \expandafter\expandafter
+    \expandafter\@gobble
+  \else
+%    \end{macrocode}
+%   And reloading in an incompatible version is an error:
+%    \begin{macrocode}
+    \expandafter\expandafter
+    \expandafter\@firstofone
+  \fi
+\fi
+  {\csname\detokenize{__kernel_dependency_version_check:Nn}\endcsname
+     \ExplLoaderFileDate{expl3.sty}}%
+%</package>
+%    \end{macrocode}
+%
+% Here we can also detect whether we're reloading.  This code goes into
+% \texttt{expl3.ltx} and \texttt{expl3.sty}, the former loaded into the
+% \LaTeXe{} format.  When this code is loaded for the first time, the
+% \cs{g_@@_reload_bool} boolean doesn't exist (\cs{else} branch of the
+% \cs{ifcsname} below), so we create it.  If the \cs{ifcsname} is true,
+% then we do \cs{ExplSyntaxOn} (because when reloading,
+% \texttt{expl3-code.tex} isn't read again), and set
+% \cs{g_@@_reload_bool} to true.
+%    \begin{macrocode}
+\ifcsname\detokenize{g_@@_reload_bool}\endcsname
+  \ExplSyntaxOn
+  \bool_gset_true:N \g_@@_reload_bool
+\else
+  \bool_new:N \g_@@_reload_bool
+\fi
+%    \end{macrocode}
+%
+% \begin{variable}{\c_@@_def_ext_tl}
+%   Needed by \LaTeXe{}, and avoiding a re-load issue.  Variables are
+%   best checked explicitly, rather than with \cs{g_@@_reload_bool}
+%   because some appear only in one of the code files, so
+%   \cs{g_@@_reload_bool} doesn't necessarily mean that the variable
+%   is already declared.
+%    \begin{macrocode}
+\tl_if_exist:NF \c_@@_def_ext_tl
+  { \tl_const:Nn \c_@@_def_ext_tl { def } }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+%   {\__kernel_sys_configuration_load:n,\__kernel_sys_configuration_load_std:n}
+%   To load configurations, we have the following cases
+%   \begin{itemize}
+%     \item \pkg{expl3} is pre-loaded: by the time any configuration loads,
+%       we have the full file loading stack, and only need the standard
+%       version of the code here.
+%     \item The package is loaded with pre-loading: we again use the standard
+%       version, but we don't test just yet.
+%     \item The package is used without pre-loaded code: we need to manually
+%       manage \pkg{expl3} syntax.
+%   \end{itemize}
+%    \begin{macrocode}
+\cs_gset_protected:Npn \__kernel_sys_configuration_load:n #1
+%<*!2ekernel>
+  {
+    \ExplSyntaxOff
+    \cs_undefine:c { ver@ #1 .def }
+    \@onefilewithoptions {#1} [ ] [ ]
+      \c_@@_def_ext_tl
+    \ExplSyntaxOn
+  }
+\cs_gset_protected:Npn \__kernel_sys_configuration_load_std:n #1
+%</!2ekernel>
+  {
+    \cs_undefine:c { ver@ #1 .def }
+    \@onefilewithoptions {#1} [ ] [ ]
+      \c_@@_def_ext_tl
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_options_clist}
+%    \begin{macrocode}
+%<*!2ekernel>
+\clist_if_exist:NF \l_@@_options_clist
+  { \clist_new:N \l_@@_options_clist }
+\DeclareOption*
+  { \clist_put_right:NV \l_@@_options_clist \CurrentOption }
+\ProcessOptions \relax
+%</!2ekernel>
+%    \end{macrocode}
+% \end{variable}
+%
+%   Pretty standard setting creation.
+%    \begin{macrocode}
+\keys_define:nn { sys }
+  {
+    backend .choices:nn =
+      { dvipdfmx , dvips , dvisvgm , luatex , pdftex , pdfmode , xdvipdfmx , xetex }
+      { \sys_load_backend:n {#1} } ,
+    check-declarations .choice: ,
+    check-declarations / true .code:n =
+      { \debug_on:n { check-declarations } } ,
+    check-declarations / false .code:n =
+      {
+        \__kernel_if_debug:TF
+          { \debug_off:n { check-declarations } }
+          { }
+      } ,
+    check-declarations .default:n = true ,
+    driver .meta:n = { backend = #1 } ,
+    enable-debug .code:n = {} , % A stub
+    log-functions .choice: ,
+    log-functions / true .code:n =
+      { \debug_on:n { log-functions } } ,
+    log-functions / false .code:n =
+      {
+        \__kernel_if_debug:TF
+          { \debug_off:n { log-functions } }
+          { }
+      } ,
+    log-functions .default:n = true ,
+    suppress-backend-headers .bool_gset_inverse:N
+      = \g__kernel_backend_header_bool ,
+    suppress-backend-headers .initial:n = false ,
+    undo-recent-deprecations .code:n = {} % A stub
+  }
+%    \end{macrocode}
+%
+% \begin{macro}{\@expl at sys@load at backend@@@@}
+%   A backend has to be in place by the start of the document: this has
+%   to be before global options are checked for use.
+%
+%   The \cs[no-index]{@expl at ...@@@@} macros defined in this package are
+%   interfaces for \LaTeXe{}.  There are currently (this will change
+%   with the next release of \LaTeXe{}) two possible cases, at this
+%   point of the code:  either \cs{@expl at sys@load at backend@@@@} (and the
+%   others) already exist because they were defined in
+%   \texttt{ltexpl.ltx} (in \texttt{2ekernel} mode) or in
+%   \texttt{expl3.ltx} (in \texttt{package} mode).
+%
+%   In \texttt{2ekernel} mode, if they exist we are using a future
+%   (2020-10-01) release of \LaTeXe{} and we don't need (and can't)
+%   patch \LaTeXe's internals because these commands are already there.
+%   Though if they don't exist in \texttt{2ekernel} mode, we're using
+%   an older version of the kernel, so we \emph{must} patch.
+%
+%   In \texttt{package} mode, if these commands exist, then we are using
+%   a version of \LaTeXe{} with \pkg{expl3} preloaded (any version)
+%   and in any case patching is already done or the macros are in the
+%   format itself, so nothing to do.
+%   But if in \texttt{package} mode these macros don't exist, we have an
+%   even older version of \LaTeXe{} which doesn't even have
+%   \pkg{expl3} preloaded, so patching is necessary.
+%
+%   All this means that in both \texttt{2ekernel} and \texttt{package}
+%   mode we have to check whether \cs{@expl at sys@load at backend@@@@}
+%   exists, and patch some \LaTeXe{} internals if it doesn't.
+%
+%   In newer \LaTeXe{}, these macros have an empty definition in
+%   \texttt{ltexpl.dtx} in case something wrong happens while loading
+%   this file (\texttt{expl3.ltx}), so they can safely be used in the
+%   \LaTeXe{} kernel.
+%
+%   \cs{@expl at sys@load at backend@@@@} is inserted right at the beginning
+%   of \cs{document}, but after closing the group started by \cs{begin}.
+%   When using \cs{tl_put_left:Nn} to patch the backend loading in
+%   \cs{document}, we need to make sure that it happens at group level
+%   zero, thus the strange |\endgroup...\begingroup| thing.
+%
+%   This chunk of code should only be executed when loading
+%   \texttt{expl3.sty} in a \LaTeXe{} without \pkg{expl3} preloaded, so
+%   we check if \cs{@expl at sys@load at backend@@@@} exists.
+%    \begin{macrocode}
+\cs_if_exist:NF \@expl at sys@load at backend@@@@
+  {
+    \tl_put_left:Nn \document
+      {
+        \endgroup
+        \@expl at sys@load at backend@@@@
+        \begingroup
+      }
+  }
+%    \end{macrocode}
+%
+%   Now we define it anyhow.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \@expl at sys@load at backend@@@@
+  {
+    \str_if_exist:NF \c_sys_backend_str
+      { \sys_load_backend:n { } }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%  Process package options.
+%    \begin{macrocode}
+%<*!2ekernel>
+\keys_set:nV { sys } \l_@@_options_clist
+\str_if_exist:NF \c_sys_backend_str
+  { \sys_load_backend:n { } }
+%</!2ekernel>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<*!2ekernel>
+\bool_if:NT \g_@@_reload_bool
+  {
+    \cs_gset_eq:NN \__kernel_sys_configuration_load:n
+      \__kernel_sys_configuration_load_std:n
+    \ExplSyntaxOff
+    \file_input_stop:
+  }
+%</!2ekernel>
+%    \end{macrocode}
+%
+% Load the dynamic part of the code, either now or during the next run.
+%    \begin{macrocode}
+\cs_if_free:cTF { ver at expl3.sty }
+  {
+    \tex_everyjob:D \exp_after:wN
+      {
+        \tex_the:D \tex_everyjob:D
+        \__kernel_sys_everyjob:
+      }
+  }
+  { \__kernel_sys_everyjob: }
+%    \end{macrocode}
+%
+% \begin{variable}{\s_@@_stop}
+%   Internal scan marks. This code has to be reload-safe, so this one
+%   has to be guarded with \cs{if_cs_exist:N} (\cs{cs_if_exist:NF}) wouldn't
+%   do because it returns false for control sequences equal to \cs{scan_stop:}.
+%    \begin{macrocode}
+\reverse_if:N \if_cs_exist:N \s_@@_stop
+  \scan_new:N \s_@@_stop
+\fi:
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@pushfilename, \@popfilename}
+% \begin{macro}{\@@_status_pop:w}
+% \begin{macro}{\@expl at push@filename@@@@}
+% \begin{macro}{\@expl at push@filename at aux@@@@}
+% \begin{macro}{\@expl at pop@filename@@@@}
+%   The idea here is to use \LaTeXe{}'s \tn{@pushfilename} and
+%   \tn{@popfilename} to track the current syntax status. This can be
+%   achieved by saving the current status flag at each push to a stack,
+%   then recovering it at the pop stage and checking if the code
+%   environment should still be active.
+%
+%   Here the code follows the same patching logic than above for
+%   \cs{@expl at sys@load at backend@@@@}.
+%    \begin{macrocode}
+\cs_if_exist:NF \@expl at push@filename@@@@
+  {
+    \tl_put_left:Nn  \@pushfilename { \@expl at push@filename@@@@ }
+    \tl_put_right:Nn \@pushfilename { \@expl at push@filename at aux@@@@ }
+  }
+\cs_gset_protected:Npn \@expl at push@filename@@@@
+  {
+    \exp_args:Ne \__kernel_file_input_push:n
+      {
+        \tl_to_str:N \@currname .
+        \tl_to_str:N \@currext
+      }
+    \tl_put_left:Ne \l_@@_status_stack_tl
+      {
+        \bool_if:NTF \l__kernel_expl_bool
+          { 1 }
+          { 0 }
+      }
+    \ExplSyntaxOff
+  }
+%    \end{macrocode}
+%   This bit of trickery is needed to grab the name of the file being loaded
+%   so we can record it.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \@expl at push@filename at aux@@@@ #1#2#3
+  {
+    \str_gset:Nn \g_file_curr_name_str {#3}
+    #1 #2 {#3}
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\cs_if_exist:NF \@expl at pop@filename@@@@
+  {
+    \tl_put_right:Nn \@popfilename
+      { \@expl at pop@filename@@@@ }
+  }
+\cs_gset_protected:Npn \@expl at pop@filename@@@@
+  {
+    \__kernel_file_input_pop:
+    \tl_if_empty:NTF \l_@@_status_stack_tl
+      { \ExplSyntaxOff }
+      { \exp_after:wN \@@_status_pop:w \l_@@_status_stack_tl \s_@@_stop }
+  }
+%    \end{macrocode}
+%   The pop auxiliary function removes the first item from the stack,
+%   saves the rest of the stack and then does the test. The flag here
+%   is not a proper \texttt{bool}, so a low-level test is used.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \@@_status_pop:w #1#2 \s_@@_stop
+  {
+    \tl_set:Nn \l_@@_status_stack_tl {#2}
+    \int_if_odd:nTF {#1}
+      { \ExplSyntaxOn }
+      { \ExplSyntaxOff }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_status_stack_tl}
+%   As \pkg{expl3} itself cannot be loaded with the code environment
+%   already active, at the end of the package \cs{ExplSyntaxOff} can
+%   safely be called.
+%    \begin{macrocode}
+\tl_if_exist:NF \l_@@_status_stack_tl
+  {
+    \tl_new:N \l_@@_status_stack_tl
+    \tl_set:Nn \l_@@_status_stack_tl { 0 }
+  }
+%    \end{macrocode}
+% \end{variable}
+%
+%  Tidy up configuration loading, as promised.
+%    \begin{macrocode}
+%<*!2ekernel>
+\cs_gset_eq:NN \__kernel_sys_configuration_load:n
+  \__kernel_sys_configuration_load_std:n
+%</!2ekernel>
+%    \end{macrocode}
+%
+% For pre-loading, we have to manually disable the syntax.
+%    \begin{macrocode}
+%<*2ekernel>
+\ExplSyntaxOff
+%</2ekernel>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</package&loader|2ekernel>
+%    \end{macrocode}
+%
+% \subsection{Generic loader}
+%
+%    \begin{macrocode}
+%<*generic>
+%    \end{macrocode}
+%
+% The generic loader starts with a test to ensure that the current format is
+% not \LaTeXe{}!
+%    \begin{macrocode}
+\begingroup
+  \def\tempa{LaTeX2e}%
+  \def\next{}%
+  \ifx\fmtname\tempa
+    \def\next
+      {%
+        \PackageInfo{expl3}{Switching from generic to LaTeX2e loader}%
+%    \end{macrocode}
+% The \cs{relax} stops \cs{RequirePackage} from scanning for a date
+% argument.  Putting \tn{endinput} \emph{after} loading the package is
+% crucial, as otherwise \tn{endinput} would close the file
+% \file{expl3.sty} at the end of its first line: indeed, as long as
+% \file{expl3.sty} is open it is impossible to close the file
+% \file{expl3-generic.tex}.
+%    \begin{macrocode}
+        \RequirePackage{expl3}\relax \endinput
+      }%
+  \fi
+\expandafter\endgroup
+\next
+%    \end{macrocode}
+%
+% Reload check and identify the package:
+% no \LaTeXe{} mechanism so this is all pretty basic.
+%    \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname ver at expl3-generic.tex\endcsname\relax
+\else
+  \immediate\write-1
+    {%
+      Package expl3 Info: The package is already loaded.%
+    }%
+  \expandafter\endinput
+\fi
+\immediate\write-1
+  {%
+    Package: expl3
+    \ExplFileDate\space
+    L3 programming layer (loader)%
+  }%
+\expandafter\edef\csname ver at expl3-generic.tex\endcsname
+  {\ExplFileDate\space L3 programming layer}%
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\ifnum\currentgrouplevel=0 %
+\else
+  \errhelp{expl3 cannot be loaded inside a group:
+    reading the code has been aborted.}%
+  \errmessage{expl3 Error: Loading attempted inside a group!}%
+  \expandafter\endinput
+\fi
+%    \end{macrocode}
+%
+% \begin{variable}[int]{\l at expl@tidy at tl}
+%   Save the category code of |@| and then set it to \enquote{letter}.
+%    \begin{macrocode}
+\expandafter\edef\csname l at expl@tidy at tl\endcsname
+  {%
+    \catcode64=\the\catcode64\relax
+    \let\expandafter\noexpand\csname l at expl@tidy at tl\endcsname
+      \noexpand\undefined
+  }%
+\catcode64=11 %
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\AtBeginDocument}
+% \begin{macro}[int]{\expl at AtBeginDocument}
+%   There are a few uses of \cs{AtBeginDocument} in the package code: the
+%   easiest way around that is to simply do the code \enquote{now}. As
+%   bundles such as \pkg{miniltx} may have defined \cs{AtBeginDocument}
+%   any existing definition is saved for restoration after the  payload.
+%    \begin{macrocode}
+\let\expl at AtBeginDocument\AtBeginDocument
+\def\AtBeginDocument#1{#1}%
+\expandafter\def\expandafter\l at expl@tidy at tl\expandafter
+  {%
+    \l at expl@tidy at tl
+    \let\AtBeginDocument\expl at AtBeginDocument
+    \let\expl at AtBeginDocument\undefined
+  }%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%  Load the business end: this leaves \cs{expl3} syntax on.
+%    \begin{macrocode}
+\input expl3-code.tex %
+%    \end{macrocode}
+%
+% A check that the bootstrap code did not abort loading: if it did,
+% bail out silently here.
+%    \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname tex\string _let:D\endcsname\relax
+  \expandafter\endinput
+\fi
+%    \end{macrocode}
+%
+% \begin{macro}{\__kernel_sys_configuration_load:n}
+%   Very basic.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \__kernel_sys_configuration_load:n #1
+  {
+    \group_begin:
+    \cs_set_protected:Npn \ProvidesExplFile
+      {
+        \char_set_catcode_space:n { `\  }
+        \ProvidesExplFileAux
+      }
+    \cs_set_protected:Npn \ProvidesExplFileAux ##1##2##3##4
+      {
+        \group_end:
+        \iow_log:e { File:~##1~##2~v##3~##4 }
+      }
+    \tex_input:D #1 .def \scan_stop:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g__kernel_backend_header_bool}
+% Load the dynamic code and standard back-end.
+%    \begin{macrocode}
+\__kernel_sys_everyjob:
+\bool_new:N \g__kernel_backend_header_bool
+\bool_gset_true:N \g__kernel_backend_header_bool
+\sys_load_backend:n { }
+%    \end{macrocode}
+% \end{macro}
+%
+%  For the generic loader, a few final steps to take. Turn of \cs{expl3}
+%  syntax and tidy up the small number of temporary changes.
+%    \begin{macrocode}
+\ExplSyntaxOff
+\l at expl@tidy at tl
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</generic>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/expl3.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3.ins	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3.ins	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,182 @@
+\iffalse meta-comment
+
+File l3.ins
+
+Copyright (C) 2011,2012,2014-2024 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.
+
+-----------------------------------------------------------------------
+
+Any modification of this file should ensure that the copyright and
+license information is placed in the derived files.
+
+\fi
+
+\let\jobname\relax
+\input docstrip %
+\askforoverwritefalse
+
+\preamble
+
+Copyright (C) 1990-2024 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.
+
+\endpreamble
+% stop docstrip adding \endinput
+\postamble
+\endpostamble
+
+\keepsilent
+
+\generate
+  {
+    \file{expl3-code.tex}
+      {
+        \from{expl3.dtx}        {package}
+        \from{l3bootstrap.dtx}  {package}
+        \from{l3names.dtx}      {package,tex}
+        \from{l3basics.dtx}     {package}
+        \from{l3expan.dtx}      {package}
+        \from{l3quark.dtx}      {package}
+        \from{l3tl.dtx}         {package}
+        \from{l3tl-build.dtx}   {package}
+        \from{l3str.dtx}        {package}
+        \from{l3seq.dtx}        {package}
+        \from{l3int.dtx}        {package}
+        \from{l3flag.dtx}       {package}
+        \from{l3prg.dtx}        {package}
+        \from{l3sys.dtx}        {package,tex}
+        \from{l3clist.dtx}      {package}
+        \from{l3token.dtx}      {package,tex}
+        \from{l3prop.dtx}       {package}
+        \from{l3msg.dtx}        {package}
+        \from{l3file.dtx}       {package}
+        \from{l3skip.dtx}       {package}
+        \from{l3keys.dtx}       {package}
+        \from{l3intarray.dtx}   {package,tex}
+        \from{l3fp.dtx}         {package}
+        \from{l3fp-aux.dtx}     {package}
+        \from{l3fp-traps.dtx}   {package}
+        \from{l3fp-round.dtx}   {package}
+        \from{l3fp-parse.dtx}   {package}
+        \from{l3fp-assign.dtx}  {package}
+        \from{l3fp-logic.dtx}   {package}
+        \from{l3fp-basics.dtx}  {package}
+        \from{l3fp-extended.dtx}{package}
+        \from{l3fp-expo.dtx}    {package}
+        \from{l3fp-trig.dtx}    {package}
+        \from{l3fp-convert.dtx} {package}
+        \from{l3fp-random.dtx}  {package}
+        \from{l3fp-types.dtx}   {package}
+        \from{l3fp-symbolic.dtx}{package}
+        \from{l3fp-functions.dtx}{package}
+        \from{l3fparray.dtx}    {package}
+        \from{l3bitset.dtx}     {package}
+        \from{l3cctab.dtx}      {package}
+        \from{l3sort.dtx}       {package}
+        \from{l3str-convert.dtx}{package}
+        \from{l3tl-analysis.dtx}{package}
+        \from{l3regex.dtx}      {package}
+        \from{l3box.dtx}        {package}
+        \from{l3color.dtx}      {package}
+        \from{l3pdf.dtx}        {package,tex}
+        \from{l3coffins.dtx}    {package}
+        \from{l3luatex.dtx}     {package,tex}
+        \from{l3unicode.dtx}    {package}
+        \from{l3text.dtx}       {package}
+        \from{l3text-case.dtx}  {package}
+        \from{l3text-map.dtx}   {package}
+        \from{l3text-purify.dtx}{package}
+        \from{l3legacy.dtx}     {package}
+        \from{l3deprecation.dtx}{package}
+      }
+  }
+
+\generate{\file{expl3.sty}        {\from{expl3.dtx}       {package,loader}}}
+\generate{\file{expl3.ltx}        {\from{expl3.dtx}       {2ekernel,loader}}}
+\generate{\file{expl3-generic.tex}{\from{expl3.dtx}       {generic,loader}}}
+
+\generate{\file{l3doc.cls}        {\from{l3doc.dtx}       {class}}}
+% not distributed:
+%\generate{\file{l3doc.ist}        {\from{l3doc.dtx}       {docist}}}
+
+% ISO-8859 encodings.
+\generate{%
+  \file{l3str-enc-iso88591.def}  {\from{l3str-convert.dtx}{iso88591}}%
+  \file{l3str-enc-iso88592.def}  {\from{l3str-convert.dtx}{iso88592}}%
+  \file{l3str-enc-iso88593.def}  {\from{l3str-convert.dtx}{iso88593}}%
+  \file{l3str-enc-iso88594.def}  {\from{l3str-convert.dtx}{iso88594}}%
+  \file{l3str-enc-iso88595.def}  {\from{l3str-convert.dtx}{iso88595}}%
+  \file{l3str-enc-iso88596.def}  {\from{l3str-convert.dtx}{iso88596}}%
+  \file{l3str-enc-iso88597.def}  {\from{l3str-convert.dtx}{iso88597}}%
+  \file{l3str-enc-iso88598.def}  {\from{l3str-convert.dtx}{iso88598}}%
+  \file{l3str-enc-iso88599.def}  {\from{l3str-convert.dtx}{iso88599}}%
+  \file{l3str-enc-iso885910.def} {\from{l3str-convert.dtx}{iso885910}}%
+  \file{l3str-enc-iso885911.def} {\from{l3str-convert.dtx}{iso885911}}%
+  \file{l3str-enc-iso885913.def} {\from{l3str-convert.dtx}{iso885913}}%
+  \file{l3str-enc-iso885914.def} {\from{l3str-convert.dtx}{iso885914}}%
+  \file{l3str-enc-iso885915.def} {\from{l3str-convert.dtx}{iso885915}}%
+  \file{l3str-enc-iso885916.def} {\from{l3str-convert.dtx}{iso885916}}%
+}
+
+\generate{\file{l3debug.def}      {\from{l3debug.dtx}      {package}}}
+
+\generate{\file{l3docstrip.tex}   {\from{l3docstrip.dtx}  {program}}}
+
+\generate{\file{l3names.def}      {\from{l3names.dtx}     {names}}}
+
+% Lua code
+
+\def\MetaPrefix{--}
+\preamble
+
+Copyright (C) 1990-2024 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.
+
+\endpreamble
+\nopostamble
+\generate{\file{expl3.lua}{
+  \from{l3luatex.dtx}{package,lua}
+  \from{l3names.dtx}{package,lua}
+  \from{l3sys.dtx}{package,lua}
+  \from{l3token.dtx}{package,lua}
+  \from{l3intarray.dtx}{package,lua}
+  \from{l3pdf.dtx}{package,lua}
+}}
+
+\endbatchfile

Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3basics.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3basics.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,3507 @@
+% \iffalse meta-comment
+%
+%% File: l3basics.dtx
+%
+% Copyright (C) 1990-2024 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 \pkg{l3basics} module\\ Basic definitions^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% As the name suggests, this module holds some basic definitions which
+% are needed by most or all other modules in this set.
+%
+% Here we describe those functions that are used all over the place.
+% By that, we mean functions dealing with the construction and testing of
+% control sequences. Furthermore the basic parts of conditional
+% processing are covered; conditional processing dealing with specific
+% data types is described in the modules specific for the respective
+% data types.
+%
+% \section{No operation functions}
+%
+% \begin{function}[EXP]{\prg_do_nothing:}
+%   \begin{syntax}
+%     \cs{prg_do_nothing:}
+%   \end{syntax}
+%   An expandable function which does nothing at all: leaves nothing
+%   in the input stream after a single expansion.
+% \end{function}
+%
+% \begin{function}{\scan_stop:}
+%   \begin{syntax}
+%     \cs{scan_stop:}
+%   \end{syntax}
+%   A non-expandable function which does nothing. Does not vanish on
+%   expansion but produces no typeset output.
+% \end{function}
+%
+% \section{Grouping material}
+%
+% \begin{function}{\group_begin:, \group_end:}
+%   \begin{syntax}
+%     \cs{group_begin:}
+%     \cs{group_end:}
+%   \end{syntax}
+%   These functions begin and end a group for definition purposes.
+%   Assignments are local to groups unless carried out in a global
+%   manner. (A small number of exceptions to this rule will be noted
+%   as necessary elsewhere in this document.) Each \cs{group_begin:}
+%   must be matched by a \cs{group_end:}, although this does not have
+%   to occur within the same function. Indeed, it is often necessary
+%   to start a group within one function and finish it within another,
+%   for example when seeking to use non-standard category codes.
+%   \begin{texnote}
+%     These are the \TeX{} primitives \tn{begingroup} and \tn{endgroup}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}{\group_insert_after:N}
+%   \begin{syntax}
+%     \cs{group_insert_after:N} \meta{token}
+%   \end{syntax}
+%   Adds \meta{token} to the list of \meta{tokens} to be inserted
+%   when the current group level ends. The list of \meta{tokens} to be
+%   inserted is empty at the beginning of a group: multiple
+%   applications of \cs{group_insert_after:N} may be used to build
+%   the inserted list one \meta{token} at a time. The current group
+%   level may be closed by a \cs{group_end:} function or by a token
+%   with category code $2$ (close-group), namely a ^^A{
+%   |}| if standard category codes apply.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{aftergroup}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2021-05-11]{\group_show_list:, \group_log_list:}
+%   \begin{syntax}
+%     \cs{group_show_list:}
+%     \cs{group_log_list:}
+%   \end{syntax}
+%   Display (to the terminal or log file) a list of the groups that are
+%   currently opened.  This is intended for tracking down problems.
+%   \begin{texnote}
+%     This is a wrapper around the \eTeX{} primitive \tn{showgroups}.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Control sequences and functions}
+%
+% As \TeX{} is a macro language, creating new functions means
+% creating macros. At point of use, a function is replaced by
+% the replacement text (\enquote{code}) in which each parameter
+% in the code (|#1|, |#2|, \emph{etc.}) is replaced the appropriate
+% arguments absorbed by the function. In the following, \meta{code}
+% is therefore used as a shorthand for \enquote{replacement text}.
+%
+% Functions which are not \enquote{protected} are fully expanded
+% inside an \texttt{e}-type or \texttt{x}-type expansion.
+% In contrast, \enquote{protected} functions are not expanded within
+% \texttt{e} and \texttt{x} expansions.
+%
+% \subsection{Defining functions}
+%
+% Functions can be created with no requirement that they are declared
+% first (in contrast to variables, which must always be declared).
+% Declaring a function before setting up the code means that the name
+% chosen is checked and an error raised if it is already in use.
+% The name of a function can be checked at the point of definition using
+% the \cs[no-index]{cs_new\ldots} functions: this is recommended for all
+% functions which are defined for the first time.
+%
+% There are three ways to define new functions.
+% All classes define a function to expand to the substitution text.
+% Within the substitution text the actual parameters are substituted
+% for the formal parameters (|#1|, |#2|, \ldots).
+% \begin{description}
+%   \item[\texttt{new}]
+%     Create a new function with the \texttt{new} scope,
+%     such as \cs{cs_new:Npn}.  The definition is global and results in
+%     an error if it is already defined.
+%   \item[\texttt{set}]
+%     Create a new function with the \texttt{set} scope,
+%     such as \cs{cs_set:Npn}. The definition is restricted to the current
+%     \TeX{} group and does not result in an error if the function is already
+%     defined.
+%   \item[\texttt{gset}]
+%     Create a new function with the \texttt{gset} scope,
+%     such as \cs{cs_gset:Npn}. The definition is global and
+%     does not result in an error if the function is already defined.
+% \end{description}
+%
+% Within each set of scope there are different ways to define a function.
+% The differences depend on restrictions on the actual parameters and
+% the expandability of the resulting function.
+% \begin{description}
+%   \item[\texttt{nopar}]
+%      Create a new function with the \texttt{nopar} restriction,
+%      such as \cs{cs_set_nopar:Npn}. The parameter may not contain
+%      \cs{par} tokens.
+%   \item[\texttt{protected}]
+%      Create a new function with the \texttt{protected} restriction,
+%      such as \cs{cs_set_protected:Npn}. The parameter may contain
+%      \cs{par} tokens but the function will not expand within an
+%      \texttt{e}-type or \texttt{x}-type expansion.
+% \end{description}
+%
+% Finally, the functions in
+% Subsections~\ref{sec:l3basics:defining-new-function-1}~and
+% \ref{sec:l3basics:defining-new-function-2} are primarily meant to define
+% \emph{base functions} only. Base functions can only have the following
+% argument specifiers:
+% \begin{description}
+%   \item[|N| and |n|] No manipulation.
+%   \item[|T| and |F|] Functionally equivalent to |n| (you are actually
+%     encouraged to use the family of |\prg_new_conditional:| functions
+%     described in Section~\ref{sec:l3prg:new-conditional-functions}).
+%   \item[|p| and |w|] These are special cases.
+% \end{description}
+%
+% The |\cs_new:| functions below (and friends) do not stop you from using
+% other argument specifiers in your function names, but they do not handle
+% expansion for you. You should define the base function and then use
+% \cs{cs_generate_variant:Nn} to generate custom variants as described in
+% Section~\ref{sec:l3expan:variants-method}.
+%
+% \subsection{Defining new functions using parameter text}
+% \label{sec:l3basics:defining-new-function-1}
+%
+% \begin{function}
+%   {
+%     \cs_new:Npn, \cs_new:cpn,
+%     \cs_new:Npe, \cs_new:cpe,
+%     \cs_new:Npx, \cs_new:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_new:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Creates \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   The definition is global and an error results if the
+%   \meta{function} is already defined.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_new_nopar:Npn, \cs_new_nopar:cpn,
+%     \cs_new_nopar:Npe, \cs_new_nopar:cpe,
+%     \cs_new_nopar:Npx, \cs_new_nopar:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_new_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Creates \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   When the \meta{function} is used the \meta{parameters} absorbed
+%   cannot contain \cs{par} tokens. The definition is global and
+%   an error results if the \meta{function} is already defined.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_new_protected:Npn, \cs_new_protected:cpn,
+%     \cs_new_protected:Npe, \cs_new_protected:cpe,
+%     \cs_new_protected:Npx, \cs_new_protected:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_new_protected:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Creates \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   The \meta{function} will not expand within an \texttt{e}-type or
+%   or \texttt{x}-type
+%   argument. The definition is global and an error results if the
+%   \meta{function} is already defined.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_new_protected_nopar:Npn, \cs_new_protected_nopar:cpn ,
+%     \cs_new_protected_nopar:Npe, \cs_new_protected_nopar:cpe ,
+%     \cs_new_protected_nopar:Npx, \cs_new_protected_nopar:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_new_protected_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Creates \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   When the \meta{function} is used the \meta{parameters} absorbed
+%   cannot contain \cs{par} tokens. The \meta{function} will not
+%   expand within an \texttt{e}-type or \texttt{x}-type argument. The definition is global
+%   and an error results if the \meta{function} is already defined.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_set:Npn, \cs_set:cpn,
+%     \cs_set:Npe, \cs_set:cpe,
+%     \cs_set:Npx, \cs_set:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_set:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   The assignment of a meaning to the \meta{function} is restricted to
+%   the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_set_nopar:Npn, \cs_set_nopar:cpn,
+%     \cs_set_nopar:Npe, \cs_set_nopar:cpe,
+%     \cs_set_nopar:Npx, \cs_set_nopar:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_set_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   When the \meta{function} is used the \meta{parameters} absorbed
+%   cannot contain \cs{par} tokens. The assignment of a meaning
+%   to the \meta{function} is restricted to the current \TeX{} group
+%   level.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_set_protected:Npn, \cs_set_protected:cpn,
+%     \cs_set_protected:Npe, \cs_set_protected:cpe,
+%     \cs_set_protected:Npx, \cs_set_protected:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_set_protected:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   The assignment of a meaning to the \meta{function} is restricted to
+%   the current \TeX{} group level. The \meta{function} will
+%   not expand within an \texttt{e}-type or \texttt{x}-type argument.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_set_protected_nopar:Npn, \cs_set_protected_nopar:cpn ,
+%     \cs_set_protected_nopar:Npe, \cs_set_protected_nopar:cpe ,
+%     \cs_set_protected_nopar:Npx, \cs_set_protected_nopar:cpx ,
+%   }
+%   \begin{syntax}
+%     \cs{cs_set_protected_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   When the \meta{function} is used the \meta{parameters} absorbed
+%   cannot contain \cs{par} tokens. The assignment of a meaning
+%   to the \meta{function} is restricted to the current \TeX{} group
+%   level. The \meta{function} will not expand within an
+%   \texttt{e}-type or \texttt{x}-type argument.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_gset:Npn, \cs_gset:cpn,
+%     \cs_gset:Npe, \cs_gset:cpe,
+%     \cs_gset:Npx, \cs_gset:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_gset:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Globally sets \meta{function} to expand to \meta{code} as replacement
+%   text. Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   The assignment of a meaning to the \meta{function} is \emph{not}
+%   restricted to the current \TeX{} group level: the assignment is
+%   global.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_gset_nopar:Npn, \cs_gset_nopar:cpn,
+%     \cs_gset_nopar:Npe, \cs_gset_nopar:cpe,
+%     \cs_gset_nopar:Npx, \cs_gset_nopar:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_gset_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Globally sets \meta{function} to expand to \meta{code} as replacement
+%   text. Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   When the \meta{function} is used the \meta{parameters} absorbed
+%   cannot contain \cs{par} tokens. The assignment of a meaning to the
+%   \meta{function} is \emph{not} restricted to the current \TeX{}
+%   group level: the assignment is global.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_gset_protected:Npn, \cs_gset_protected:cpn,
+%     \cs_gset_protected:Npe, \cs_gset_protected:cpe,
+%     \cs_gset_protected:Npx, \cs_gset_protected:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_gset_protected:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Globally sets \meta{function} to expand to \meta{code} as replacement
+%   text. Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   The assignment of a meaning to the \meta{function} is \emph{not}
+%   restricted to the current \TeX{} group level: the assignment is
+%   global. The \meta{function} will not expand within an
+%   \texttt{e}-type or \texttt{x}-type argument.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_gset_protected_nopar:Npn, \cs_gset_protected_nopar:cpn,
+%     \cs_gset_protected_nopar:Npe, \cs_gset_protected_nopar:cpe,
+%     \cs_gset_protected_nopar:Npx, \cs_gset_protected_nopar:cpx
+%   }
+%   \begin{syntax}
+%     \cs{cs_gset_protected_nopar:Npn} \meta{function} \meta{parameters} \Arg{code}
+%   \end{syntax}
+%   Globally sets \meta{function} to expand to \meta{code} as replacement
+%   text. Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+%   \emph{etc.}) will be replaced by those absorbed by the function.
+%   When the \meta{function} is used the \meta{parameters} absorbed
+%   cannot contain \cs{par} tokens. The assignment of a meaning to the
+%   \meta{function} is \emph{not} restricted to the current \TeX{}
+%   group level: the assignment is global. The \meta{function} will
+%   not expand within an \texttt{e}-type or \texttt{x}-type argument.
+% \end{function}
+%
+% \subsection{Defining new functions using the signature}
+% \label{sec:l3basics:defining-new-function-2}
+%
+% \begin{function}
+%   {
+%     \cs_new:Nn, \cs_new:cn,
+%     \cs_new:Ne, \cs_new:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_new:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Creates \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function. The definition is global and
+%   an error results if the \meta{function} is already defined.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_new_nopar:Nn, \cs_new_nopar:cn,
+%     \cs_new_nopar:Ne, \cs_new_nopar:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_new_nopar:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Creates \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function.  When the \meta{function} is used the \meta{parameters}
+%   absorbed cannot contain \cs{par} tokens. The definition is global and
+%   an error results if the \meta{function} is already defined.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_new_protected:Nn, \cs_new_protected:cn,
+%     \cs_new_protected:Ne, \cs_new_protected:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_new_protected:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Creates \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function. The \meta{function} will not expand within an \texttt{e}-type
+%   or \texttt{x}-type argument. The definition is global and
+%   an error results if the \meta{function} is already defined.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_new_protected_nopar:Nn, \cs_new_protected_nopar:cn,
+%     \cs_new_protected_nopar:Ne, \cs_new_protected_nopar:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_new_protected_nopar:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Creates \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function.  When the \meta{function} is used the \meta{parameters}
+%   absorbed cannot contain \cs{par} tokens. The \meta{function} will not
+%   expand within an \texttt{e}-type or \texttt{x}-type argument. The definition is global and
+%   an error results if the \meta{function} is already defined.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_set:Nn, \cs_set:cn,
+%     \cs_set:Ne, \cs_set:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_set:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function.
+%   The assignment of a meaning to the \meta{function} is restricted to
+%   the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_set_nopar:Nn, \cs_set_nopar:cn,
+%     \cs_set_nopar:Ne, \cs_set_nopar:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_set_nopar:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function.  When the \meta{function} is used the \meta{parameters}
+%   absorbed cannot contain \cs{par} tokens.
+%   The assignment of a meaning to the \meta{function} is restricted to
+%   the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_set_protected:Nn, \cs_set_protected:cn,
+%     \cs_set_protected:Ne, \cs_set_protected:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_set_protected:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function. The \meta{function} will not expand within an \texttt{e}-type
+%   or \texttt{x}-type argument.
+%   The assignment of a meaning to the \meta{function} is restricted to
+%   the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_set_protected_nopar:Nn, \cs_set_protected_nopar:cn,
+%     \cs_set_protected_nopar:Ne, \cs_set_protected_nopar:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_set_protected_nopar:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function.  When the \meta{function} is used the \meta{parameters}
+%   absorbed cannot contain \cs{par} tokens. The \meta{function} will not
+%   expand within an \texttt{e}-type or \texttt{x}-type argument.
+%   The assignment of a meaning to the \meta{function} is restricted to
+%   the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_gset:Nn, \cs_gset:cn,
+%     \cs_gset:Ne, \cs_gset:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_gset:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function.
+%   The assignment of a meaning to the \meta{function} is  global.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_gset_nopar:Nn, \cs_gset_nopar:cn,
+%     \cs_gset_nopar:Ne, \cs_gset_nopar:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_gset_nopar:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function.  When the \meta{function} is used the \meta{parameters}
+%   absorbed cannot contain \cs{par} tokens.
+%   The assignment of a meaning to the \meta{function} is global.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_gset_protected:Nn, \cs_gset_protected:cn,
+%     \cs_gset_protected:Ne, \cs_gset_protected:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_gset_protected:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function. The \meta{function} will not expand within an \texttt{e}-type
+%   or \texttt{x}-type argument.
+%   The assignment of a meaning to the \meta{function} is  global.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \cs_gset_protected_nopar:Nn, \cs_gset_protected_nopar:cn,
+%     \cs_gset_protected_nopar:Ne, \cs_gset_protected_nopar:ce
+%   }
+%   \begin{syntax}
+%     \cs{cs_gset_protected_nopar:Nn} \meta{function} \Arg{code}
+%   \end{syntax}
+%   Sets \meta{function} to expand to \meta{code} as replacement text.
+%   Within the \meta{code}, the number of \meta{parameters} is detected
+%   automatically from the function signature. These \meta{parameters}
+%   (|#1|, |#2|, \emph{etc.}) will be replaced by those absorbed by the
+%   function.  When the \meta{function} is used the \meta{parameters}
+%   absorbed cannot contain \cs{par} tokens. The \meta{function} will not
+%   expand within an \texttt{e}-type or \texttt{x}-type argument.
+%   The assignment of a meaning to the \meta{function} is global.
+% \end{function}
+%
+% \begin{function}[updated = 2012-01-14]
+%   {
+%     \cs_generate_from_arg_count:NNnn,
+%     \cs_generate_from_arg_count:NNno,
+%     \cs_generate_from_arg_count:cNnn,
+%     \cs_generate_from_arg_count:Ncnn
+%   }
+%   \begin{syntax}
+%     \cs{cs_generate_from_arg_count:NNnn} \meta{function} \meta{creator} \Arg{number} \Arg{code}
+%   \end{syntax}
+%   Uses the \meta{creator} function (which should have signature
+%   |Npn|, for example \cs{cs_new:Npn}) to define a \meta{function}
+%   which takes \meta{number} arguments and has \meta{code} as
+%   replacement text. The \meta{number} of arguments is an integer expression,
+%   evaluated as detailed for \cs{int_eval:n}.
+% \end{function}
+%
+% \subsection{Copying control sequences}
+%
+% Control sequences (not just functions as defined above) can
+% be set to have the same meaning using the functions described
+% here. Making two control sequences equivalent means that the
+% second control sequence is a \emph{copy} of the first (rather than
+% a pointer to it). Thus the old and new control sequence are not
+% tied together: changes to one are not reflected in the other.
+%
+% In the following text \enquote{cs} is used as an abbreviation for
+% \enquote{control sequence}.
+%
+% \begin{function}
+%   {\cs_new_eq:NN, \cs_new_eq:Nc, \cs_new_eq:cN, \cs_new_eq:cc}
+%   \begin{syntax}
+%     \cs{cs_new_eq:NN} \meta{cs_1} \meta{cs_2}
+%     \cs{cs_new_eq:NN} \meta{cs_1} \meta{token}
+%   \end{syntax}
+%   Globally creates \meta{control sequence_1} and sets it to have the same
+%   meaning as \meta{control sequence_2} or <token>.
+%   The second control sequence may
+%   subsequently be altered without affecting the copy.
+% \end{function}
+%
+% \begin{function}
+%   {\cs_set_eq:NN, \cs_set_eq:Nc, \cs_set_eq:cN, \cs_set_eq:cc}
+%   \begin{syntax}
+%     \cs{cs_set_eq:NN} \meta{cs_1} \meta{cs_2}
+%     \cs{cs_set_eq:NN} \meta{cs_1} \meta{token}
+%   \end{syntax}
+%   Sets \meta{control sequence_1} to have the same meaning as
+%   \meta{control sequence_2} (or <token>).
+%   The second control sequence may subsequently be
+%   altered without affecting the copy. The assignment of a meaning
+%   to the \meta{control sequence_1} is restricted to the current
+%   \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+%   {\cs_gset_eq:NN, \cs_gset_eq:Nc, \cs_gset_eq:cN, \cs_gset_eq:cc}
+%   \begin{syntax}
+%     \cs{cs_gset_eq:NN} \meta{cs_1} \meta{cs_2}
+%     \cs{cs_gset_eq:NN} \meta{cs_1} \meta{token}
+%   \end{syntax}
+%   Globally sets \meta{control sequence_1} to have the same meaning as
+%   \meta{control sequence_2} (or <token>).
+%   The second control sequence may subsequently be
+%   altered without affecting the copy. The assignment of a meaning to
+%   the \meta{control sequence_1} is \emph{not} restricted to the current
+%   \TeX{} group level: the assignment is global.
+% \end{function}
+%
+% \subsection{Deleting control sequences}
+%
+% There are occasions where control sequences need to be deleted.
+% This is handled in a very simple manner.
+%
+% \begin{function}[updated = 2011-09-15]{\cs_undefine:N, \cs_undefine:c}
+%   \begin{syntax}
+%     \cs{cs_undefine:N} \meta{control sequence}
+%   \end{syntax}
+%   Sets \meta{control sequence} to be globally undefined.
+% \end{function}
+%
+% \subsection{Showing control sequences}
+%
+% \begin{function}[EXP, updated = 2011-12-22]{\cs_meaning:N, \cs_meaning:c}
+%   \begin{syntax}
+%     \cs{cs_meaning:N} \meta{control sequence}
+%   \end{syntax}
+%   This function expands to the \emph{meaning} of the \meta{control sequence}
+%   control sequence. For a macro, this includes the \meta{replacement text}.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{meaning}.
+%     For tokens that are not control sequences, it is more logical to
+%     use \cs{token_to_meaning:N}.
+%     The \texttt{c} variant correctly reports undefined arguments.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[updated = 2017-02-14]{\cs_show:N, \cs_show:c}
+%   \begin{syntax}
+%     \cs{cs_show:N} \meta{control sequence}
+%   \end{syntax}
+%   Displays the definition of the \meta{control sequence} on the
+%   terminal.
+%   \begin{texnote}
+%     This is similar to the \TeX{} primitive \tn{show}, wrapped to a
+%     fixed number of characters per line.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2014-08-22, updated = 2017-02-14]{\cs_log:N, \cs_log:c}
+%   \begin{syntax}
+%     \cs{cs_log:N} \meta{control sequence}
+%   \end{syntax}
+%   Writes the definition of the \meta{control sequence} in the log
+%   file.  See also \cs{cs_show:N} which displays the result in the
+%   terminal.
+% \end{function}
+%
+% \subsection{Converting to and from control sequences}
+%
+% \begin{function}[EXP]{\use:c}
+%   \begin{syntax}
+%     \cs{use:c} \Arg{control sequence name}
+%   \end{syntax}
+%   Expands the \meta{control sequence name} until only characters
+%   remain, and then converts this into a control sequence. This process
+%   requires two expansions.  As in other \texttt{c}-type arguments the
+%   \meta{control sequence name} must, when fully expanded, consist of
+%   character tokens, typically a mixture of category code $10$ (space),
+%   $11$ (letter) and $12$ (other).
+% \end{function}
+%
+% As an example of the \cs{use:c} function, both
+%   \begin{verbatim}
+%     \use:c { a b c }
+%   \end{verbatim}
+%   and
+%   \begin{verbatim}
+%     \tl_new:N  \l_my_tl
+%     \tl_set:Nn \l_my_tl { a b c }
+%     \use:c { \tl_use:N \l_my_tl }
+%   \end{verbatim}
+%   would be equivalent to
+%   \begin{verbatim}
+%     \abc
+%   \end{verbatim}
+%   after two expansions of \cs{use:c}.
+%
+% \begin{function}[noTF, EXP, added = 2012-11-10]
+%   {\cs_if_exist_use:N, \cs_if_exist_use:c}
+%   \begin{syntax}
+%     \cs{cs_if_exist_use:N} \meta{control sequence}
+%     \cs{cs_if_exist_use:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{control sequence} is currently defined
+%   according to the conditional \cs{cs_if_exist:NTF}
+%   (whether as a function or another control sequence type), and if it
+%   is inserts the  \meta{control sequence} into the input stream followed
+%   by the \meta{true code}.  Otherwise the \meta{false code} is used.
+% \end{function}
+%
+% \begin{function}[EXP]{\cs:w, \cs_end:}
+%   \begin{syntax}
+%     \cs{cs:w} \meta{control sequence name} \cs{cs_end:}
+%   \end{syntax}
+%   Converts the given \meta{control sequence name} into a single
+%   control sequence token. This process requires one expansion.
+%   The content for \meta{control sequence name} may be literal
+%   material or from other expandable functions. The
+%   \meta{control sequence name} must, when fully expanded, consist
+%   of character tokens which are not active: typically
+%   of category code $10$ (space), $11$ (letter)
+%   or $12$ (other), or a mixture of these.
+%   \begin{texnote}
+%     These are the \TeX{} primitives \tn{csname} and \tn{endcsname}.
+%   \end{texnote}
+% \end{function}
+%
+% As an example of the \cs{cs:w} and \cs{cs_end:} functions, both
+%   \begin{verbatim}
+%     \cs:w a b c \cs_end:
+%   \end{verbatim}
+%   and
+%   \begin{verbatim}
+%     \tl_new:N  \l_my_tl
+%     \tl_set:Nn \l_my_tl { a b c }
+%     \cs:w \tl_use:N \l_my_tl \cs_end:
+%   \end{verbatim}
+%   would be equivalent to
+%   \begin{verbatim}
+%     \abc
+%   \end{verbatim}
+%   after one expansion of \cs{cs:w}.
+%
+% \begin{function}[EXP]{\cs_to_str:N}
+%   \begin{syntax}
+%     \cs{cs_to_str:N} \meta{control sequence}
+%   \end{syntax}
+%   Converts the given \meta{control sequence} into a series of
+%   characters with category code $12$ (other), except spaces,
+%   of category code $10$. The result does \emph{not} include
+%   the current escape token, contrarily to \cs{token_to_str:N}.
+%   Full expansion of this function requires exactly $2$ expansion
+%   steps, and so an \texttt{e}-type or \texttt{x}-type expansion, or two
+%   \texttt{o}-type expansions are required to
+%   convert the \meta{control sequence} to a sequence of characters
+%   in the input stream. In most cases, an \texttt{f}-expansion
+%   is correct as well, but this loses a space at the start
+%   of the result.
+% \end{function}
+%
+% \section{Analysing control sequences}
+%
+% \begin{function}[EXP, added = 2018-04-06]{\cs_split_function:N}
+%   \begin{syntax}
+%     \cs{cs_split_function:N} \meta{function}
+%   \end{syntax}
+%   Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
+%   before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
+%   This information is then placed in the input stream
+%   in three parts: the \meta{name}, the
+%   \meta{signature} and a logic token indicating if a colon was found
+%   (to differentiate variables from function names). The \meta{name}
+%   does not include the escape character, and both the \meta{name} and
+%   \meta{signature} are made up of tokens with category code $12$
+%   (other).
+% \end{function}
+%
+% The next three functions decompose \TeX{} macros into their
+% constituent parts: if the \meta{token} passed is not a macro then no
+% decomposition can occur. In the latter case, all three functions leave
+% \cs{scan_stop:} in the input stream.
+%
+% \begin{function}[EXP, added = 2019-02-27]{\cs_prefix_spec:N}
+%   \begin{syntax}
+%     \cs{cs_prefix_spec:N} \meta{token}
+%   \end{syntax}
+%   If the \meta{token} is a macro, this function leaves the applicable
+%   \TeX{} prefixes in input stream as a string of tokens of category
+%   code $12$ (with spaces having category code $10$). Thus for example
+%   \begin{verbatim}
+%     \cs_set:Npn \next:nn #1#2 { x #1~y #2 }
+%     \cs_prefix_spec:N \next:nn
+%   \end{verbatim}
+%   leaves |\long| in the input stream. If the \meta{token} is
+%   not a macro then \cs{scan_stop:} is left in the input stream.
+%   \begin{texnote}
+%     The prefix can be empty, |\long|, |\protected| or
+%     |\protected\long| with backslash replaced by the current escape
+%     character.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2022-06-24]{\cs_parameter_spec:N}
+%   \begin{syntax}
+%     \cs{cs_parameter_spec:N} \meta{token}
+%   \end{syntax}
+%   If the \meta{token} is a macro, this function leaves the primitive
+%   \TeX{} parameter specification in input stream as a string of
+%   character tokens of category code $12$ (with spaces having category
+%   code $10$). Thus for example
+%   \begin{verbatim}
+%     \cs_set:Npn \next:nn #1#2 { x #1 y #2 }
+%     \cs_parameter_spec:N \next:nn
+%   \end{verbatim}
+%   leaves |#1#2| in the input stream. If the \meta{token} is
+%   not a macro then \cs{scan_stop:} is left in the input stream.
+%   \begin{texnote}
+%     If the parameter specification contains the string |->|, then the
+%     function produces incorrect results.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2019-02-27]{\cs_replacement_spec:N, \cs_replacement_spec:c}
+%   \begin{syntax}
+%     \cs{cs_replacement_spec:N} \meta{token}
+%   \end{syntax}
+%   If the \meta{token} is a macro, this function leaves the replacement
+%   text in input stream as a string of character tokens of category
+%   code $12$ (with spaces having category code $10$). Thus for example
+%   \begin{verbatim}
+%     \cs_set:Npn \next:nn #1#2 { x #1~y #2 }
+%     \cs_replacement_spec:N \next:nn
+%   \end{verbatim}
+%   leaves \verb*|x#1 y#2| in the input stream. If the \meta{token} is
+%   not a macro then \cs{scan_stop:} is left in the input stream.
+%   \begin{texnote}
+%     If the parameter specification contains the string |->|, then the
+%     function produces incorrect results.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Using or removing tokens and arguments}
+%
+% Tokens in the input can be read and used or read and discarded.
+% If one or more tokens are wrapped in braces then when absorbing them
+% the outer set is removed. At the same time, the category code
+% of each token is set when the token is read by a function (if it
+% is read more than once, the category code is determined by
+% the situation in force when first function absorbs the token).
+%
+% \begin{function}[EXP]{\use:n, \use:nn, \use:nnn, \use:nnnn}
+%   \begin{syntax}
+%     \cs{use:n}    \Arg{group_1}
+%     \cs{use:nn}   \Arg{group_1} \Arg{group_2}
+%     \cs{use:nnn}  \Arg{group_1} \Arg{group_2} \Arg{group_3}
+%     \cs{use:nnnn} \Arg{group_1} \Arg{group_2} \Arg{group_3} \Arg{group_4}
+%   \end{syntax}
+%   As illustrated, these functions absorb between one and four
+%   arguments, as indicated by the argument specifier. The braces
+%   surrounding each argument are removed and the remaining tokens are
+%   left in the input stream. The category code of these tokens is
+%   also fixed by this process (if it has not already been by some
+%   other absorption). All of these functions require only a single
+%   expansion to operate, so that one expansion of
+%   \begin{verbatim}
+%     \use:nn { abc } { { def } }
+%   \end{verbatim}
+%   results in the input stream containing
+%   \begin{verbatim}
+%     abc { def }
+%   \end{verbatim}
+%   \emph{i.e.} only the outer braces are removed.
+%   \begin{texnote}
+%     The \cs{use:n} function is equivalent to \LaTeXe{}'s \tn{@firstofone}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]
+%   {
+%     \use_i:nn, \use_ii:nn ,
+%     \use_i:nnn , \use_ii:nnn , \use_iii:nnn ,
+%     \use_i:nnnn, \use_ii:nnnn, \use_iii:nnnn, \use_iv:nnnn  ,
+%     \use_i:nnnnn, \use_ii:nnnnn, \use_iii:nnnnn, \use_iv:nnnnn ,
+%       \use_v:nnnnn ,
+%     \use_i:nnnnnn, \use_ii:nnnnnn, \use_iii:nnnnnn, \use_iv:nnnnnn ,
+%       \use_v:nnnnnn , \use_vi:nnnnnn ,
+%     \use_i:nnnnnnn, \use_ii:nnnnnnn, \use_iii:nnnnnnn, \use_iv:nnnnnnn ,
+%       \use_v:nnnnnnn , \use_vi:nnnnnnn , \use_vii:nnnnnnn ,
+%     \use_i:nnnnnnnn, \use_ii:nnnnnnnn, \use_iii:nnnnnnnn, \use_iv:nnnnnnnn ,
+%       \use_v:nnnnnnnn , \use_vi:nnnnnnnn , \use_vii:nnnnnnnn , \use_viii:nnnnnnnn ,
+%     \use_i:nnnnnnnnn, \use_ii:nnnnnnnnn, \use_iii:nnnnnnnnn, \use_iv:nnnnnnnnn ,
+%       \use_v:nnnnnnnnn , \use_vi:nnnnnnnnn , \use_vii:nnnnnnnnn , \use_viii:nnnnnnnnn ,
+%       \use_ix:nnnnnnnnn
+%   }
+%    \begin{syntax}
+%     \cs{use_i:nn} \Arg{arg_1} \Arg{arg_2}
+%     \cs{use_i:nnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3}
+%     \cs{use_i:nnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4}
+%     \cs{use_i:nnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5}
+%     \cs{use_i:nnnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5} \Arg{arg_6}
+%     \cs{use_i:nnnnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5} \Arg{arg_6} \Arg{arg_7}
+%     \cs{use_i:nnnnnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5} \Arg{arg_6} \Arg{arg_7} \Arg{arg_8}
+%     \cs{use_i:nnnnnnnnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3} \Arg{arg_4} \Arg{arg_5} \Arg{arg_6} \Arg{arg_7} \Arg{arg_8} \Arg{arg_9}
+%   \end{syntax}
+%   These functions absorb a number ($n$) arguments from the input stream.
+%   They then discard all arguments other than that indicated by the roman
+%   numeral, which is left in the input stream. For example, \cs{use_i:nn}
+%   discards the second argument, and leaves the content of the first
+%   argument in the input stream.
+%   The category code
+%   of these tokens is also fixed (if it has not already been by
+%   some other absorption). A single expansion is needed for the
+%   functions to take effect.
+% \end{function}
+%
+% \begin{function}[EXP]{\use_i_ii:nnn}
+%   \begin{syntax}
+%     \cs{use_i_ii:nnn} \Arg{arg_1} \Arg{arg_2} \Arg{arg_3}
+%   \end{syntax}
+%   This function absorbs three arguments and leaves the content of the
+%   first and second in the input stream. The category code of
+%   these tokens is also fixed (if it has not already been by
+%   some other absorption). A single expansion is needed for the
+%   function to take effect. An example:
+%   \begin{verbatim}
+%     \use_i_ii:nnn { abc } { { def } } { ghi }
+%   \end{verbatim}
+%   results in the input stream containing
+%   \begin{verbatim}
+%     abc { def }
+%   \end{verbatim}
+%   \emph{i.e.} the outer braces are removed and the third group
+%   is removed.
+% \end{function}
+%
+% \begin{function}[EXP, added = 2019-06-02]{\use_ii_i:nn}
+%   \begin{syntax}
+%     \cs{use_ii_i:nn} \Arg{arg_1} \Arg{arg_2}
+%   \end{syntax}
+%   This function absorbs two arguments and leaves the content of the
+%   second and first in the input stream. The category code of
+%   these tokens is also fixed (if it has not already been by
+%   some other absorption). A single expansion is needed for the
+%   function to take effect.
+% \end{function}
+%
+% \begin{function}[EXP]
+%   {
+%     \use_none:n         ,
+%     \use_none:nn        ,
+%     \use_none:nnn       ,
+%     \use_none:nnnn      ,
+%     \use_none:nnnnn     ,
+%     \use_none:nnnnnn    ,
+%     \use_none:nnnnnnn   ,
+%     \use_none:nnnnnnnn  ,
+%     \use_none:nnnnnnnnn
+%   }
+%   \begin{syntax}
+%     \cs{use_none:n} \Arg{group_1}
+%   \end{syntax}
+%   These functions absorb between one and nine groups from the
+%   input stream, leaving nothing on the resulting input stream.
+%   These functions work after a single expansion. One or more of the
+%   \texttt{n} arguments may be an unbraced single token
+%   (\emph{i.e.}~an \texttt{N} argument).
+%   \begin{texnote}
+%     These are equivalent to \LaTeXe{}'s \tn{@gobble}, \tn{@gobbletwo},
+%     \emph{etc.}
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2018-06-18, updated = 2023-07-05]{\use:e}
+%   \begin{syntax}
+%     \cs{use:e} \Arg{expandable tokens}
+%   \end{syntax}
+%   Fully expands the \meta{token list} in an \texttt{e}-type manner,
+%   in which parameter character (usually~|#|) need not be doubled, \emph{and}
+%   the function remains fully expandable.
+%   \begin{texnote}
+%     \cs{use:e} is a wrapper around the primitive \tn{expanded}.
+%     It requires two expansions to complete its action.
+%   \end{texnote}
+% \end{function}
+%
+% \subsection{Selecting tokens from delimited arguments}
+%
+% A different kind of function for selecting tokens from the token
+% stream are those that use delimited arguments.
+%
+% \begin{function}[EXP]
+%   {
+%     \use_none_delimit_by_q_nil:w,
+%     \use_none_delimit_by_q_stop:w,
+%     \use_none_delimit_by_q_recursion_stop:w
+%   }
+%   \begin{syntax}
+%    \cs{use_none_delimit_by_q_nil:w} \meta{balanced text} \cs{q_nil}
+%    \cs{use_none_delimit_by_q_stop:w} \meta{balanced text} \cs{q_stop}
+%    \cs{use_none_delimit_by_q_recursion_stop:w} \meta{balanced text} \cs{q_recursion_stop}
+%   \end{syntax}
+%   Absorb the \meta{balanced text} from the input stream delimited by
+%   the marker given in the function name, leaving nothing in the
+%   input stream.
+% \end{function}
+%
+% \begin{function}[EXP]
+%   {
+%     \use_i_delimit_by_q_nil:nw,
+%     \use_i_delimit_by_q_stop:nw,
+%     \use_i_delimit_by_q_recursion_stop:nw
+%   }
+%   \begin{syntax}
+%    \cs{use_i_delimit_by_q_nil:nw} \Arg{inserted tokens} \meta{balanced text} \cs{q_nil}
+%    \cs{use_i_delimit_by_q_stop:nw} \Arg{inserted tokens} \meta{balanced text} \cs{q_stop}
+%    \cs{use_i_delimit_by_q_recursion_stop:nw} \Arg{inserted tokens} \meta{balanced text} \cs{q_recursion_stop}
+%   \end{syntax}
+%   Absorb the \meta{balanced text} from the input stream delimited by
+%   the marker given in the function name, leaving \meta{inserted tokens}
+%   in the input stream for further processing.
+% \end{function}
+%
+% \section{Predicates and conditionals}
+%
+% \LaTeX3 has three concepts for conditional flow processing:
+% \begin{description}
+%   \item[Branching conditionals]
+%     Functions that carry out a test and then execute, depending on its
+%     result, either the code supplied as the \meta{true code} or the
+%     \meta{false code}.
+%     These arguments are denoted with |T| and |F|, respectively. An
+%     example would be
+%     \begin{quote}
+%      |\cs_if_free:cTF {abc}| \Arg{true code} \Arg{false code}
+%     \end{quote}
+%     a function that turns the first argument into a control sequence
+%     (since it's marked as |c|) then checks whether this control sequence
+%     is still free and then depending on the result carries out the code in
+%     the second argument (true case) or in the third argument (false
+%     case).
+%
+%     These type of functions are known as \enquote{conditionals};
+%     whenever a |TF| function is defined it is usually accompanied by
+%     |T| and |F| functions as well. These are provided for convenience when
+%     the branch only needs to go a single way. Package writers are free to
+%     choose which types to define but the kernel definitions always
+%     provide all three versions.
+%
+%     Important to note is that these branching conditionals with \meta{true
+%     code} and/or \meta{false code} are always defined in a way that the
+%     code of the chosen alternative can operate on following tokens in
+%     the input stream.
+%
+%     These conditional functions may or may not be fully expandable, but if
+%     they are expandable they are accompanied by a \enquote{predicate}
+%     for the same test as described below.
+%
+%   \item[Predicates]
+%     \enquote{Predicates} are functions that return a special type of
+%     boolean value which can be tested by the boolean expression parser.
+%     All functions of this type
+%     are expandable and have names that end with |_p| in the
+%     description part.  For example,
+%     \begin{quote}
+%       \cs{cs_if_free_p:N}
+%     \end{quote}
+%     would be a predicate function for the same type of test as the
+%     conditional described above. It would return \enquote{true} if its
+%     argument (a single token denoted by |N|) is still free for definition.
+%     It would be used in constructions like
+%     \begin{quote}
+%       |\bool_if:nTF {| \\
+%       \verb"  \cs_if_free_p:N \l_tmpz_tl || \cs_if_free_p:N \g_tmpz_tl " \\
+%       |}|
+%       \Arg{true code} \Arg{false code}
+%     \end{quote}
+%
+%     For each predicate defined, a \enquote{branching conditional}
+%     also exists that behaves like a conditional described above.
+%
+%   \item[Primitive conditionals]
+%      There is a third variety of conditional, which is the original
+%      concept used in plain \TeX{} and \LaTeXe{}. Their use is discouraged
+%      in \pkg{expl3} (although still used in low-level definitions)
+%      because they are more fragile and in many cases require more
+%      expansion control (hence more code) than the two types of
+%      conditionals described above.
+% \end{description}
+%
+% \subsection{Tests on control sequences}
+%
+% \begin{function}[EXP,pTF]{\cs_if_eq:NN}
+%   \begin{syntax}
+%     \cs{cs_if_eq_p:NN} \meta{cs_1} \meta{cs_2}
+%     \cs{cs_if_eq:NNTF} \meta{cs_1} \meta{cs_2} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Compares the definition of two \meta{control sequences} and
+%   is logically \texttt{true} if they are the same, \emph{i.e.}~if they have exactly
+%   the same definition when examined with \cs{cs_show:N}.
+% \end{function}
+%
+% \begin{function}[EXP,pTF]{\cs_if_exist:N, \cs_if_exist:c}
+%   \begin{syntax}
+%     \cs{cs_if_exist_p:N} \meta{control sequence}
+%     \cs{cs_if_exist:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{control sequence} is currently defined
+%   (whether as a function or another control sequence type). Any
+%   definition of \meta{control sequence} other than \tn{relax}
+%   evaluates as \texttt{true}.
+% \end{function}
+%
+% \begin{function}[EXP,pTF]{\cs_if_free:N, \cs_if_free:c}
+%   \begin{syntax}
+%     \cs{cs_if_free_p:N} \meta{control sequence}
+%     \cs{cs_if_free:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{control sequence} is currently free to
+%   be defined. This test is \texttt{false} if the
+%   \meta{control sequence} currently exists (as defined by
+%   \cs{cs_if_exist:NTF}).
+% \end{function}
+%
+% \subsection{Primitive conditionals}
+%
+% The \eTeX{} engine itself provides many different conditionals. Some
+% expand whatever comes after them and others don't. Hence the names
+% for these underlying functions often contains a |:w| part but
+% higher level functions are often available. See for instance
+% \cs{int_compare_p:nNn} which is a wrapper for \cs{if_int_compare:w}.
+%
+% Certain conditionals deal with specific data types like boxes and
+% fonts and are described there. The ones described below are either
+% the universal conditionals or deal with control sequences. We
+% prefix primitive conditionals with |\if_|, except for \cs{if:w}.
+%
+% \begin{function}[EXP]
+%   {\if_true:, \if_false:, \else:, \fi:, \reverse_if:N}
+%   \begin{syntax}
+%     "\if_true:" <true code> "\else:" <false code> "\fi:" \\
+%     "\if_false:" <true code> "\else:" <false code> "\fi:" \\
+%     "\reverse_if:N" <primitive conditional>
+%   \end{syntax}
+%   "\if_true:" always executes <true code>, while "\if_false:" always
+%   executes <false code>. "\reverse_if:N" reverses any two-way primitive
+%   conditional. "\else:" and "\fi:" delimit the branches of the
+%   conditional. The function "\or:" is documented in \pkg{l3int} and
+%   used in case switches.
+%   \begin{texnote}
+%     \cs{if_true:} and \cs{if_false:} are equivalent to their corresponding
+%     \TeX{} primitive conditionals \tn{iftrue} and \tn{iffalse};
+%     \cs{else:} and \cs{fi:} are the \TeX{} primitives \tn{else} and \tn{fi};
+%     \cs{reverse_if:N} is the \eTeX{} primitive \tn{unless}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\if_meaning:w}
+%   \begin{syntax}
+%     "\if_meaning:w" <arg_1> <arg_2> <true code> "\else:" <false code> "\fi:"
+%   \end{syntax}
+%   "\if_meaning:w" executes <true code> when <arg_1> and <arg_2> are the same,
+%   otherwise it executes <false code>.
+%   <arg_1> and <arg_2> could be functions, variables, tokens; in all cases the
+%   \emph{unexpanded} definitions are compared.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{ifx}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\if:w, \if_charcode:w, \if_catcode:w}
+%   \begin{syntax}
+%     "\if:w" <token(s)> <true code> "\else:" <false code> "\fi:" \\
+%     "\if_catcode:w" <token(s)> <true code> "\else:" <false code> "\fi:"
+%   \end{syntax}
+%   "\if_charcode:w" is an alternative name for "\if:w".
+%   These conditionals expand \meta{token(s)} until two
+%   unexpandable tokens \meta{token_1} and \meta{token_2} are found;
+%   any further tokens up to the next unbalanced "\else:" are the true branch,
+%   ending with \meta{true code}. It is executed if the condition is fulfilled,
+%   otherwise \meta{false code} is executed.
+%   You can omit "\else:" when just in front of "\fi:" and
+%   you can nest "\if...\else:...\fi:" constructs inside the true branch or the
+%   \meta{false code}.
+%   With "\exp_not:N", you can prevent the expansion of a token. 
+%
+%   "\if_catcode:w"
+%   tests if \meta{token_1} and \meta{token_2} have the same category code whereas
+%   "\if:w" and \cs{if_charcode:w} test if they have the same character code.
+%   \begin{texnote}
+%     \cs{if:w} and \cs{if_charcode:w} are both the \TeX{} primitive \tn{if}.
+%     \cs{if_catcode:w} is the \TeX{} primitive \tn{ifcat}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\if_cs_exist:N, \if_cs_exist:w}
+%   \begin{syntax}
+%     "\if_cs_exist:N" <cs> <true code> "\else:" <false code> "\fi:" \\
+%     "\if_cs_exist:w" <tokens> "\cs_end:" <true code> "\else:" <false code> "\fi:"
+%   \end{syntax}
+%   Check if <cs> appears in the hash table or if the control sequence
+%   that can be formed from <tokens> appears in the hash table. The
+%   latter function does not turn the control sequence in question into
+%   "\scan_stop:"! This can be useful when dealing with control
+%   sequences which cannot be entered as a single token.
+%   \begin{texnote}
+%     These are the \TeX{} primitives \tn{ifdefined} and \tn{ifcsname}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]
+%   {
+%     \if_mode_horizontal:, \if_mode_vertical:,
+%     \if_mode_math:, \if_mode_inner:
+%   }
+%   \begin{syntax}
+%     "\if_mode_horizontal:" <true code> "\else:" <false code> "\fi:"
+%   \end{syntax}
+%   Execute <true code> if currently in horizontal mode, otherwise
+%   execute <false code>. Similar for the other functions.
+%   \begin{texnote}
+%     These are the \TeX{} primitives \tn{ifhmode}, \tn{ifvmode}, \tn{ifmmode},
+%     and~\tn{ifinner}.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Starting a paragraph}
+%
+% \begin{function}[added = 2017-07-04]{\mode_leave_vertical:}
+%   \begin{syntax}
+%     \cs{mode_leave_vertical:}
+%   \end{syntax}
+%   Ensures that \TeX{} is not in vertical (inter-paragraph) mode. In
+%   horizontal or math mode this command has no effect, in vertical mode it
+%   switches to horizontal mode, and inserts a box of width
+%   \tn{parindent}, followed by the \tn{everypar} token list.
+%   \begin{texnote}
+%     This results in the contents of the \tn{everypar} token register being
+%     inserted, after \cs{mode_leave_vertical:} is complete. Notice that in
+%     contrast to the \LaTeXe{} \tn{leavevmode} approach, no box is used
+%     by the method implemented here.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Debugging support}
+%
+% \begin{function}[added = 2017-07-16, updated = 2023-05-23]{\debug_on:n, \debug_off:n}
+%   \begin{syntax}
+%     \cs{debug_on:n} |{| \meta{comma-separated list} |}|
+%     \cs{debug_off:n} |{| \meta{comma-separated list} |}|
+%   \end{syntax}
+%   Turn on and off within a group various debugging code, some of which
+%   is also available as \pkg{expl3} load-time options.  The items that
+%   can be used in the \meta{list} are
+%   \begin{itemize}
+%     \item \texttt{check-declarations} that checks all \pkg{expl3}
+%       variables used were previously declared and that local/global
+%       variables (based on their name or on their first assignment) are
+%       only locally/globally assigned;
+%     \item \texttt{check-expressions} that checks integer, dimension,
+%       skip, and muskip expressions are not terminated prematurely;
+%     \item \texttt{deprecation} that makes deprecated commands produce errors;
+%     \item \texttt{log-functions} that logs function definitions and
+%       variable declarations;
+%     \item \texttt{all} that does all of the above.
+%   \end{itemize}
+%   Providing these as switches rather than options allows testing code
+%   even if it relies on other packages: load all other packages, call
+%   \cs{debug_on:n}, and load the code that one is interested in
+%   testing.
+% \end{function}
+%
+% \begin{function}[added = 2017-11-28]{\debug_suspend:, \debug_resume:}
+%   \begin{syntax}
+%     \cs{debug_suspend:} \ldots{} \cs{debug_resume:}
+%   \end{syntax}
+%   Suppress (locally) errors and logging from \texttt{debug} commands,
+%   except for the \texttt{deprecation} errors.  These pairs
+%   of commands can be nested.  This can be used around pieces of code
+%   that are known to fail checks, if such failures should be ignored.
+%   See for instance \pkg{l3cctab} and \pkg{l3coffins}.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3basics} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{Renaming some \TeX{} primitives (again)}
+%
+% Having given all the \TeX{} primitives a consistent name, we need to
+% give sensible names to the ones we actually want to use.
+% These will be defined as needed in the appropriate modules, but we
+% do a few now, just to get started.\footnote{This renaming gets expensive
+% in terms of csname usage, an alternative scheme would be to just use
+% the \cs[no-index]{tex_\ldots:D} name in the cases where no good alternative exists.}
+%
+% \begin{macro}[EXP]
+%   {
+%     \if_true:, \if_false:, \or:, \else:, \fi:, \reverse_if:N,
+%     \if:w, \if_charcode:w, \if_catcode:w, \if_meaning:w
+%   }
+%   Then some conditionals.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \if_true:           \tex_iftrue:D
+\tex_global:D \tex_let:D \if_false:          \tex_iffalse:D
+\tex_global:D \tex_let:D \or:                \tex_or:D
+\tex_global:D \tex_let:D \else:              \tex_else:D
+\tex_global:D \tex_let:D \fi:                \tex_fi:D
+\tex_global:D \tex_let:D \reverse_if:N       \tex_unless:D
+\tex_global:D \tex_let:D \if:w               \tex_if:D
+\tex_global:D \tex_let:D \if_charcode:w      \tex_if:D
+\tex_global:D \tex_let:D \if_catcode:w       \tex_ifcat:D
+\tex_global:D \tex_let:D \if_meaning:w       \tex_ifx:D
+\tex_global:D \tex_let:D \if_bool:N          \tex_ifodd:D
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {
+%     \if_mode_math:,
+%     \if_mode_horizontal:,
+%     \if_mode_vertical:,
+%     \if_mode_inner:
+%   }
+%   \TeX{} lets us detect some if its modes.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \if_mode_math:       \tex_ifmmode:D
+\tex_global:D \tex_let:D \if_mode_horizontal: \tex_ifhmode:D
+\tex_global:D \tex_let:D \if_mode_vertical:   \tex_ifvmode:D
+\tex_global:D \tex_let:D \if_mode_inner:      \tex_ifinner:D
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\if_cs_exist:N, \if_cs_exist:w, \cs:w, \cs_end:}
+%   Building csnames and testing if control sequences exist.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \if_cs_exist:N      \tex_ifdefined:D
+\tex_global:D \tex_let:D \if_cs_exist:w      \tex_ifcsname:D
+\tex_global:D \tex_let:D \cs:w               \tex_csname:D
+\tex_global:D \tex_let:D \cs_end:            \tex_endcsname:D
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\exp_after:wN, \exp_not:N, \exp_not:n}
+%    The five |\exp_| functions are used in the \pkg{l3expan} module
+%    where they are described.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \exp_after:wN       \tex_expandafter:D
+\tex_global:D \tex_let:D \exp_not:N          \tex_noexpand:D
+\tex_global:D \tex_let:D \exp_not:n          \tex_unexpanded:D
+\tex_global:D \tex_let:D \exp:w              \tex_romannumeral:D
+\tex_global:D \tex_chardef:D \exp_end:  = 0 ~
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\token_to_meaning:N, \cs_meaning:N}
+%   Examining a control sequence or token.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \token_to_meaning:N \tex_meaning:D
+\tex_global:D \tex_let:D \cs_meaning:N       \tex_meaning:D
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\tl_to_str:n, \token_to_str:N, \__kernel_tl_to_str:w}
+%   Making strings.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \tl_to_str:n          \tex_detokenize:D
+\tex_global:D \tex_let:D \token_to_str:N       \tex_string:D
+\tex_global:D \tex_let:D \__kernel_tl_to_str:w \tex_detokenize:D
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\scan_stop:, \group_begin:, \group_end:}
+%    The next three are basic functions for which there also exist
+%    versions that are safe inside alignments. These safe versions are
+%    defined in the \pkg{l3prg} module.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \scan_stop:         \tex_relax:D
+\tex_global:D \tex_let:D \group_begin:       \tex_begingroup:D
+\tex_global:D \tex_let:D \group_end:         \tex_endgroup:D
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%<@@=int>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP]{\if_int_compare:w, \@@_to_roman:w}
+%   For integers.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \if_int_compare:w   \tex_ifnum:D
+\tex_global:D \tex_let:D \@@_to_roman:w     \tex_romannumeral:D
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\group_insert_after:N}
+%   Adding material after the end of a group.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \group_insert_after:N \tex_aftergroup:D
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\exp_args:Nc, \exp_args:cc}
+%   Discussed in \pkg{l3expan}, but needed much earlier.
+%    \begin{macrocode}
+\tex_long:D \tex_gdef:D \exp_args:Nc #1#2
+  { \exp_after:wN #1 \cs:w #2 \cs_end: }
+\tex_long:D \tex_gdef:D \exp_args:cc #1#2
+  { \cs:w #1 \exp_after:wN \cs_end: \cs:w #2 \cs_end: }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, documented-as=\token_to_meaning:N]
+%   {\token_to_meaning:c, \token_to_str:c, \cs_meaning:c}
+%   A small number of variants defined by hand.
+%   Some of the necessary functions
+%   (\cs{use_i:nn}, \cs{use_ii:nn}, and \cs{exp_args:NNc}) are not
+%   defined at that point yet, but will be defined before those variants
+%   are used.  The \cs{cs_meaning:c} command must check for an undefined
+%   control sequence to avoid defining it mistakenly.
+%    \begin{macrocode}
+\tex_gdef:D \token_to_str:c { \exp_args:Nc \token_to_str:N }
+\tex_long:D \tex_gdef:D \cs_meaning:c #1
+  {
+    \if_cs_exist:w #1 \cs_end:
+      \exp_after:wN \use_i:nn
+    \else:
+      \exp_after:wN \use_ii:nn
+    \fi:
+    { \exp_args:Nc \cs_meaning:N {#1} }
+    { \tl_to_str:n {undefined} }
+  }
+\tex_global:D \tex_let:D \token_to_meaning:c = \cs_meaning:c
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Defining some constants}
+%
+% \begin{variable}{\c_zero_int}
+%   We need the constant \cs{c_zero_int}
+%   which is used by some functions in current module. The
+%   rest are defined in the \pkg{l3int} module -- at least for the
+%   ones that can be defined with \cs{tex_chardef:D} or
+%   \cs{tex_mathchardef:D}. For other constants the \pkg{l3int} module is
+%   required but it can't be used until the allocation has been set
+%   up properly!
+%    \begin{macrocode}
+\tex_global:D \tex_chardef:D \c_zero_int    = 0 ~
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_max_register_int}
+%   This is here as this particular integer is needed in modules
+%   loaded before \pkg{l3int}, and is documented in \pkg{l3int}.
+%   \LuaTeX{} and those which contain parts of the Omega extensions have
+%   more registers available than \eTeX{}.
+%    \begin{macrocode}
+\tex_ifdefined:D \tex_luatexversion:D
+  \tex_global:D \tex_chardef:D \c_max_register_int = 65 535 ~
+\tex_else:D
+  \tex_ifdefined:D \tex_omathchardef:D
+    \tex_global:D \tex_omathchardef:D \c_max_register_int = 65535 ~
+  \tex_else:D
+    \tex_global:D \tex_mathchardef:D \c_max_register_int = 32767 ~
+  \tex_fi:D
+\tex_fi:D
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Defining functions}
+%
+% We start by providing functions for the typical definition
+% functions. First the global ones.
+%
+% \begin{macro}
+%   {
+%     \cs_gset_nopar:Npn           , \cs_gset_nopar:Npe           , \cs_gset_nopar:Npx           ,
+%     \cs_gset:Npn                 , \cs_gset:Npe                 , \cs_gset:Npx                 ,
+%     \cs_gset_protected_nopar:Npn , \cs_gset_protected_nopar:Npe , \cs_gset_protected_nopar:Npx ,
+%     \cs_gset_protected:Npn       , \cs_gset_protected:Npe       , \cs_gset_protected:Npx
+%   }
+%   All assignment functions in \LaTeX3 should be naturally protected;
+%   after all, the \TeX{} primitives for assignments are and it can be
+%   a cause of problems if others aren't.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \cs_gset_nopar:Npn           \tex_gdef:D
+\tex_global:D \tex_let:D \cs_gset_nopar:Npe           \tex_xdef:D
+\tex_global:D \tex_let:D \cs_gset_nopar:Npx           \tex_xdef:D
+\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset:Npn
+  { \tex_long:D \tex_gdef:D }
+\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset:Npe
+  { \tex_long:D \tex_xdef:D }
+\tex_global:D \tex_let:D \cs_gset:Npx \cs_gset:Npe
+\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset_protected_nopar:Npn
+  { \tex_protected:D \tex_gdef:D }
+\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset_protected_nopar:Npe
+  { \tex_protected:D \tex_xdef:D }
+\tex_global:D \tex_let:D \cs_gset_protected_nopar:Npx \cs_gset_protected_nopar:Npe
+\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset_protected:Npn
+  { \tex_protected:D \tex_long:D \tex_gdef:D }
+\tex_protected:D \tex_long:D \tex_gdef:D \cs_gset_protected:Npe
+  { \tex_protected:D \tex_long:D \tex_xdef:D }
+\tex_global:D \tex_let:D \cs_gset_protected:Npx \cs_gset_protected:Npe
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \cs_set_nopar:Npn           , \cs_set_nopar:Npe           , \cs_set_nopar:Npx           ,
+%     \cs_set:Npn                 , \cs_set:Npe                 , \cs_set:Npx                 ,
+%     \cs_set_protected_nopar:Npn , \cs_set_protected_nopar:Npe , \cs_set_protected_nopar:Npx ,
+%     \cs_set_protected:Npn       , \cs_set_protected:Npe       , \cs_set_protected:Npx
+%   }
+%   Local versions of the above functions.
+%    \begin{macrocode}
+\tex_global:D \tex_let:D \cs_set_nopar:Npn           \tex_def:D
+\tex_global:D \tex_let:D \cs_set_nopar:Npe           \tex_edef:D
+\tex_global:D \tex_let:D \cs_set_nopar:Npx           \tex_edef:D
+\cs_gset_protected:Npn \cs_set:Npn
+  { \tex_long:D \tex_def:D }
+\cs_gset_protected:Npn \cs_set:Npe
+  { \tex_long:D \tex_edef:D }
+\tex_global:D \tex_let:D \cs_set:Npx \cs_set:Npe
+\cs_gset_protected:Npn \cs_set_protected_nopar:Npn
+  { \tex_protected:D \tex_def:D }
+\cs_gset_protected:Npn \cs_set_protected_nopar:Npe
+  { \tex_protected:D \tex_edef:D }
+\tex_global:D \tex_let:D \cs_set_protected_nopar:Npx \cs_set_protected_nopar:Npe
+\cs_gset_protected:Npn \cs_set_protected:Npn
+  { \tex_protected:D \tex_long:D \tex_def:D }
+\cs_gset_protected:Npn \cs_set_protected:Npe
+  { \tex_protected:D \tex_long:D \tex_edef:D }
+\tex_global:D \tex_let:D \cs_set_protected:Npx \cs_set_protected:Npe
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Selecting tokens}
+%
+%    \begin{macrocode}
+%<@@=exp>
+%    \end{macrocode}
+%
+% \begin{variable}{\l_@@_internal_tl}
+%   Scratch token list variable for \pkg{l3expan}, used by \cs{use:x},
+%   used in defining conditionals.  We don't use |tl| methods because
+%   \pkg{l3basics} is loaded earlier.
+%    \begin{macrocode}
+\cs_gset_nopar:Npn \l_@@_internal_tl { }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[EXP]{\use:c}
+%    This macro grabs its argument and returns a csname from it.
+%    \begin{macrocode}
+\cs_gset:Npn \use:c #1 { \cs:w #1 \cs_end: }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[deprecated]{\use:x}
+%   Fully expands its argument and passes it to the input stream. Uses
+%   the reserved \cs{l_@@_internal_tl} which we've set up above.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \use:x #1
+  {
+    \cs_set_nopar:Npx \l_@@_internal_tl {#1}
+    \l_@@_internal_tl
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%<@@=use>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP]{\use:e}
+%    \begin{macrocode}
+\cs_gset:Npn \use:e #1 { \tex_expanded:D {#1} }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%<@@=exp>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP]{\use:n, \use:nn, \use:nnn, \use:nnnn}
+%    These macros grab their arguments and return them back to the input
+%    (with outer braces removed).
+%    \begin{macrocode}
+\cs_gset:Npn \use:n    #1       {#1}
+\cs_gset:Npn \use:nn   #1#2     {#1#2}
+\cs_gset:Npn \use:nnn  #1#2#3   {#1#2#3}
+\cs_gset:Npn \use:nnnn #1#2#3#4 {#1#2#3#4}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\use_i:nn, \use_ii:nn}
+%    The equivalent to \LaTeXe{}'s \tn{@firstoftwo} and \tn{@secondoftwo}.
+%    \begin{macrocode}
+\cs_gset:Npn \use_i:nn  #1#2 {#1}
+\cs_gset:Npn \use_ii:nn #1#2 {#2}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {
+%     \use_i:nnn , \use_ii:nnn , \use_iii:nnn ,
+%     \use_i:nnnn, \use_ii:nnnn, \use_iii:nnnn, \use_iv:nnnn  ,
+%     \use_i:nnnnn, \use_ii:nnnnn, \use_iii:nnnnn, \use_iv:nnnnn ,
+%       \use_v:nnnnn ,
+%     \use_i:nnnnnn, \use_ii:nnnnnn, \use_iii:nnnnnn, \use_iv:nnnnnn ,
+%       \use_v:nnnnnn , \use_vi:nnnnnn ,
+%     \use_i:nnnnnnn, \use_ii:nnnnnnn, \use_iii:nnnnnnn, \use_iv:nnnnnnn ,
+%       \use_v:nnnnnnn , \use_vi:nnnnnnn , \use_vii:nnnnnnn ,
+%     \use_i:nnnnnnnn, \use_ii:nnnnnnnn, \use_iii:nnnnnnnn, \use_iv:nnnnnnnn ,
+%       \use_v:nnnnnnnn , \use_vi:nnnnnnnn , \use_vii:nnnnnnnn , \use_viii:nnnnnnnn ,
+%     \use_i:nnnnnnnnn, \use_ii:nnnnnnnnn, \use_iii:nnnnnnnnn, \use_iv:nnnnnnnnn ,
+%       \use_v:nnnnnnnnn , \use_vi:nnnnnnnnn , \use_vii:nnnnnnnnn , \use_viii:nnnnnnnnn ,
+%       \use_ix:nnnnnnnnn
+%   }
+%   We also need something for picking up arguments from a longer list.
+%    \begin{macrocode}
+\cs_gset:Npn \use_i:nnn    #1#2#3 {#1}
+\cs_gset:Npn \use_ii:nnn   #1#2#3 {#2}
+\cs_gset:Npn \use_iii:nnn  #1#2#3 {#3}
+\cs_gset:Npn \use_i:nnnn   #1#2#3#4 {#1}
+\cs_gset:Npn \use_ii:nnnn  #1#2#3#4 {#2}
+\cs_gset:Npn \use_iii:nnnn #1#2#3#4 {#3}
+\cs_gset:Npn \use_iv:nnnn  #1#2#3#4 {#4}
+\cs_gset:Npn \use_i:nnnnn   #1#2#3#4#5 {#1}
+\cs_gset:Npn \use_ii:nnnnn  #1#2#3#4#5 {#2}
+\cs_gset:Npn \use_iii:nnnnn #1#2#3#4#5 {#3}
+\cs_gset:Npn \use_iv:nnnnn  #1#2#3#4#5 {#4}
+\cs_gset:Npn \use_v:nnnnn   #1#2#3#4#5 {#5}
+\cs_gset:Npn \use_i:nnnnnn   #1#2#3#4#5#6 {#1}
+\cs_gset:Npn \use_ii:nnnnnn  #1#2#3#4#5#6 {#2}
+\cs_gset:Npn \use_iii:nnnnnn #1#2#3#4#5#6 {#3}
+\cs_gset:Npn \use_iv:nnnnnn  #1#2#3#4#5#6 {#4}
+\cs_gset:Npn \use_v:nnnnnn   #1#2#3#4#5#6 {#5}
+\cs_gset:Npn \use_vi:nnnnnn  #1#2#3#4#5#6 {#6}
+\cs_gset:Npn \use_i:nnnnnnn   #1#2#3#4#5#6#7 {#1}
+\cs_gset:Npn \use_ii:nnnnnnn  #1#2#3#4#5#6#7 {#2}
+\cs_gset:Npn \use_iii:nnnnnnn #1#2#3#4#5#6#7 {#3}
+\cs_gset:Npn \use_iv:nnnnnnn  #1#2#3#4#5#6#7 {#4}
+\cs_gset:Npn \use_v:nnnnnnn   #1#2#3#4#5#6#7 {#5}
+\cs_gset:Npn \use_vi:nnnnnnn  #1#2#3#4#5#6#7 {#6}
+\cs_gset:Npn \use_vii:nnnnnnn #1#2#3#4#5#6#7 {#7}
+\cs_gset:Npn \use_i:nnnnnnnn    #1#2#3#4#5#6#7#8 {#1}
+\cs_gset:Npn \use_ii:nnnnnnnn   #1#2#3#4#5#6#7#8 {#2}
+\cs_gset:Npn \use_iii:nnnnnnnn  #1#2#3#4#5#6#7#8 {#3}
+\cs_gset:Npn \use_iv:nnnnnnnn   #1#2#3#4#5#6#7#8 {#4}
+\cs_gset:Npn \use_v:nnnnnnnn    #1#2#3#4#5#6#7#8 {#5}
+\cs_gset:Npn \use_vi:nnnnnnnn   #1#2#3#4#5#6#7#8 {#6}
+\cs_gset:Npn \use_vii:nnnnnnnn  #1#2#3#4#5#6#7#8 {#7}
+\cs_gset:Npn \use_viii:nnnnnnnn #1#2#3#4#5#6#7#8 {#8}
+\cs_gset:Npn \use_i:nnnnnnnnn    #1#2#3#4#5#6#7#8#9 {#1}
+\cs_gset:Npn \use_ii:nnnnnnnnn   #1#2#3#4#5#6#7#8#9 {#2}
+\cs_gset:Npn \use_iii:nnnnnnnnn  #1#2#3#4#5#6#7#8#9 {#3}
+\cs_gset:Npn \use_iv:nnnnnnnnn   #1#2#3#4#5#6#7#8#9 {#4}
+\cs_gset:Npn \use_v:nnnnnnnnn    #1#2#3#4#5#6#7#8#9 {#5}
+\cs_gset:Npn \use_vi:nnnnnnnnn   #1#2#3#4#5#6#7#8#9 {#6}
+\cs_gset:Npn \use_vii:nnnnnnnnn  #1#2#3#4#5#6#7#8#9 {#7}
+\cs_gset:Npn \use_viii:nnnnnnnnn #1#2#3#4#5#6#7#8#9 {#8}
+\cs_gset:Npn \use_ix:nnnnnnnnn   #1#2#3#4#5#6#7#8#9 {#9}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\use_i_ii:nnn}
+%    \begin{macrocode}
+\cs_gset:Npn \use_i_ii:nnn #1#2#3 {#1#2}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\use_ii_i:nn}
+%    \begin{macrocode}
+\cs_gset:Npn \use_ii_i:nn #1#2 { #2 #1 }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[EXP]
+%   {
+%     \use_none_delimit_by_q_nil:w  ,
+%     \use_none_delimit_by_q_stop:w ,
+%     \use_none_delimit_by_q_recursion_stop:w
+%   }
+%   Functions that gobble everything until they see either \cs{q_nil},
+%   \cs{q_stop}, or \cs{q_recursion_stop}, respectively.
+%    \begin{macrocode}
+\cs_gset:Npn \use_none_delimit_by_q_nil:w  #1 \q_nil  { }
+\cs_gset:Npn \use_none_delimit_by_q_stop:w #1 \q_stop { }
+\cs_gset:Npn \use_none_delimit_by_q_recursion_stop:w #1 \q_recursion_stop { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {
+%     \use_i_delimit_by_q_nil:nw  ,
+%     \use_i_delimit_by_q_stop:nw ,
+%     \use_i_delimit_by_q_recursion_stop:nw
+%   }
+%   Same as above but execute first argument after gobbling. Very useful
+%   when you need to skip the rest of a mapping sequence but want an
+%   easy way to control what should be expanded next.
+%    \begin{macrocode}
+\cs_gset:Npn \use_i_delimit_by_q_nil:nw  #1#2 \q_nil  {#1}
+\cs_gset:Npn \use_i_delimit_by_q_stop:nw #1#2 \q_stop {#1}
+\cs_gset:Npn \use_i_delimit_by_q_recursion_stop:nw
+  #1#2 \q_recursion_stop {#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Gobbling tokens from input}
+%
+% \begin{macro}[EXP]
+%   {
+%     \use_none:n,
+%     \use_none:nn,
+%     \use_none:nnn,
+%     \use_none:nnnn,
+%     \use_none:nnnnn,
+%     \use_none:nnnnnn,
+%     \use_none:nnnnnnn,
+%     \use_none:nnnnnnnn,
+%     \use_none:nnnnnnnnn
+%   }
+%   To gobble tokens from the input we use a standard naming convention:
+%   the number of tokens gobbled is given by the number of |n|'s
+%   following the |:| in the name. Although we could define functions to
+%   remove ten arguments or more using separate calls of
+%   \cs{use_none:nnnnn}, this is very non-intuitive to the programmer
+%   who will assume that expanding such a function once takes care
+%   of gobbling all the tokens in one go.
+%    \begin{macrocode}
+\cs_gset:Npn \use_none:n         #1                 { }
+\cs_gset:Npn \use_none:nn        #1#2               { }
+\cs_gset:Npn \use_none:nnn       #1#2#3             { }
+\cs_gset:Npn \use_none:nnnn      #1#2#3#4           { }
+\cs_gset:Npn \use_none:nnnnn     #1#2#3#4#5         { }
+\cs_gset:Npn \use_none:nnnnnn    #1#2#3#4#5#6       { }
+\cs_gset:Npn \use_none:nnnnnnn   #1#2#3#4#5#6#7     { }
+\cs_gset:Npn \use_none:nnnnnnnn  #1#2#3#4#5#6#7#8   { }
+\cs_gset:Npn \use_none:nnnnnnnnn #1#2#3#4#5#6#7#8#9 { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Debugging and patching later definitions}
+%
+%    \begin{macrocode}
+%<@@=debug>
+%    \end{macrocode}
+%
+% \begin{macro}{\__kernel_if_debug:TF}
+%   A more meaningful test of whether debugging is enabled than messing
+%   up with guards.  We can also more easily change the logic in one
+%   place then. This is needed primarily for deprecations.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \__kernel_if_debug:TF #1#2 {#2}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\debug_on:n, \debug_off:n}
+%   Stubs.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \debug_on:n #1
+  {
+    \sys_load_debug:
+    \cs_if_exist:NT \@@_all_on:
+      { \debug_on:n {#1} }
+  }
+\cs_gset_protected:Npn \debug_off:n #1
+  {
+    \sys_load_debug:
+    \cs_if_exist:NT \@@_all_on:
+      { \debug_off:n {#1} }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\debug_suspend:, \debug_resume:}
+%    \begin{macrocode}
+\cs_gset_protected:Npn \debug_suspend: { }
+\cs_gset_protected:Npn \debug_resume: { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\__kernel_deprecation_code:nn}
+% \begin{variable}{\g_@@_deprecation_on_tl, \g_@@_deprecation_off_tl}
+%   Make deprecated commands throw errors if the user requests it.
+%   This relies on two token lists, filled up in \pkg{l3deprecation}.
+%    \begin{macrocode}
+\cs_gset_nopar:Npn \g_@@_deprecation_on_tl { }
+\cs_gset_nopar:Npn \g_@@_deprecation_off_tl { }
+\cs_gset_protected:Npn \__kernel_deprecation_code:nn #1#2
+  {
+    \tl_gput_right:Nn \g_@@_deprecation_on_tl {#1}
+    \tl_gput_right:Nn \g_@@_deprecation_off_tl {#2}
+  }
+%    \end{macrocode}
+% \end{variable}
+% \end{macro}
+%
+% \subsection{Conditional processing and definitions}
+%
+%    \begin{macrocode}
+%<@@=prg>
+%    \end{macrocode}
+%
+% Underneath any predicate function (|_p|) or other conditional forms
+% (|TF|, etc.) is a built-in logic saying that it after all of the
+% testing and processing must return the \meta{state} this leaves
+% \TeX{} in. Therefore, a simple user interface could be something like
+% \begin{verbatim}
+%   \if_meaning:w #1#2
+%     \prg_return_true:
+%   \else:
+%     \if_meaning:w #1#3
+%       \prg_return_true:
+%     \else:
+%       \prg_return_false:
+%     \fi:
+%   \fi:
+% \end{verbatim}
+% Usually, a \TeX{} programmer would have to insert a number of
+% \cs{exp_after:wN}s to ensure the state value is returned at exactly
+% the point where the last conditional is finished.  However, that
+% obscures the code and forces the \TeX{} programmer to prove that
+% he/she knows the $2^{n}-1$ table.  We therefore provide the simpler
+% interface.
+%
+% \begin{macro}[EXP]{\prg_return_true:, \prg_return_false:}
+%   The idea here is that \cs{exp:w} expands fully any
+%   \cs{else:} and \cs{fi:} that are waiting to be discarded,
+%   before reaching the \cs{exp_end:} which leaves an empty expansion.
+%   The code can then leave either the first or second argument in the
+%   input stream. This means that all of the branching code has to contain
+%   at least two tokens: see how the logical tests are actually implemented
+%   to see this.
+%    \begin{macrocode}
+\cs_gset:Npn \prg_return_true:
+  { \exp_after:wN \use_i:nn  \exp:w }
+\cs_gset:Npn \prg_return_false:
+  { \exp_after:wN \use_ii:nn \exp:w}
+%    \end{macrocode}
+%   An extended state space could be implemented by including a more
+%   elaborate function in place of \cs{use_i:nn}/\cs{use_ii:nn}. Provided
+%   two arguments are absorbed then the code would work.
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_use_none_delimit_by_q_recursion_stop:w}
+%   Private version of \cs{use_none_delimit_by_q_recursion_stop:w}.
+%    \begin{macrocode}
+\cs_gset:Npn \@@_use_none_delimit_by_q_recursion_stop:w
+  #1 \q_@@_recursion_stop { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \prg_set_conditional:Npnn           ,
+%     \prg_gset_conditional:Npnn          ,
+%     \prg_new_conditional:Npnn           ,
+%     \prg_set_protected_conditional:Npnn ,
+%     \prg_gset_protected_conditional:Npnn,
+%     \prg_new_protected_conditional:Npnn
+%   }
+% \begin{macro}{\@@_generate_conditional_parm:NNNpnn}
+%   The user functions for the types using parameter text from the
+%   programmer. The various functions only differ by which function is
+%   used for the assignment. For those |Npnn| type functions, we must
+%   grab the parameter text, reading everything up to a left brace
+%   before continuing. Then split the base function into name and
+%   signature, and feed \Arg{name} \Arg{signature} \meta{boolean}
+%   \Arg{set~or~new} \Arg{maybe~protected} \Arg{parameters} |{TF,...}|
+%   \Arg{code} to the auxiliary function responsible for defining all
+%   conditionals.
+%   Note that |e| stands for expandable and |p| for protected.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \prg_set_conditional:Npnn
+  { \@@_generate_conditional_parm:NNNpnn \cs_set:Npn e }
+\cs_gset_protected:Npn \prg_gset_conditional:Npnn
+  { \@@_generate_conditional_parm:NNNpnn \cs_gset:Npn e }
+\cs_gset_protected:Npn \prg_new_conditional:Npnn
+  { \@@_generate_conditional_parm:NNNpnn \cs_new:Npn e }
+\cs_gset_protected:Npn \prg_set_protected_conditional:Npnn
+  { \@@_generate_conditional_parm:NNNpnn \cs_set_protected:Npn p }
+\cs_gset_protected:Npn \prg_gset_protected_conditional:Npnn
+  { \@@_generate_conditional_parm:NNNpnn \cs_gset_protected:Npn p }
+\cs_gset_protected:Npn \prg_new_protected_conditional:Npnn
+  { \@@_generate_conditional_parm:NNNpnn \cs_new_protected:Npn p }
+\cs_gset_protected:Npn \@@_generate_conditional_parm:NNNpnn #1#2#3#4#
+  {
+    \use:e
+      {
+        \@@_generate_conditional:nnNNNnnn
+          \cs_split_function:N #3
+      }
+      #1 #2 {#4}
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \prg_set_conditional:Nnn           ,
+%     \prg_gset_conditional:Nnn          ,
+%     \prg_new_conditional:Nnn           ,
+%     \prg_set_protected_conditional:Nnn ,
+%     \prg_gset_protected_conditional:Nnn,
+%     \prg_new_protected_conditional:Nnn
+%   }
+% \begin{macro}
+%   {
+%     \@@_generate_conditional_count:NNNnn ,
+%     \@@_generate_conditional_count:nnNNNnn
+%   }
+%   The user functions for the types automatically inserting the correct
+%   parameter text based on the signature. The various functions only
+%   differ by which function is used for the assignment. Split the base
+%   function into name and signature.  The second auxiliary generates
+%   the parameter text from the number of letters in the signature.
+%   Then feed \Arg{name} \Arg{signature} \meta{boolean} \Arg{set~or~new}
+%   \Arg{maybe~protected} \Arg{parameters} |{TF,...}| \Arg{code} to the
+%   auxiliary function responsible for defining all conditionals.  If
+%   the \meta{signature} has more than $9$ letters, the definition is
+%   aborted since \TeX{} macros have at most $9$ arguments.  The
+%   erroneous case where the function name contains no colon is captured
+%   later.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \prg_set_conditional:Nnn
+  { \@@_generate_conditional_count:NNNnn \cs_set:Npn e }
+\cs_gset_protected:Npn \prg_gset_conditional:Nnn
+  { \@@_generate_conditional_count:NNNnn \cs_set:Npn e }
+\cs_gset_protected:Npn \prg_new_conditional:Nnn
+  { \@@_generate_conditional_count:NNNnn \cs_new:Npn e }
+\cs_gset_protected:Npn \prg_set_protected_conditional:Nnn
+  { \@@_generate_conditional_count:NNNnn \cs_set_protected:Npn p }
+\cs_gset_protected:Npn \prg_gset_protected_conditional:Nnn
+  { \@@_generate_conditional_count:NNNnn \cs_gset_protected:Npn p }
+\cs_gset_protected:Npn \prg_new_protected_conditional:Nnn
+  { \@@_generate_conditional_count:NNNnn \cs_new_protected:Npn p }
+\cs_gset_protected:Npn \@@_generate_conditional_count:NNNnn #1#2#3
+  {
+    \use:e
+      {
+        \@@_generate_conditional_count:nnNNNnn
+        \cs_split_function:N #3
+      }
+      #1 #2
+  }
+\cs_gset_protected:Npn \@@_generate_conditional_count:nnNNNnn #1#2#3#4#5
+  {
+    \__kernel_cs_parm_from_arg_count:nnF
+      { \@@_generate_conditional:nnNNNnnn {#1} {#2} #3 #4 #5 }
+      { \tl_count:n {#2} }
+      {
+        \msg_error:nnee { kernel } { bad-number-of-arguments }
+          { \token_to_str:c { #1 : #2 } }
+          { \tl_count:n {#2} }
+        \use_none:nn
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \@@_generate_conditional:nnNNNnnn,
+%     \@@_generate_conditional:NNnnnnNw,
+%     \@@_generate_conditional_test:w,
+%     \@@_generate_conditional_fast:nw,
+%   }
+%   The workhorse here is going through a list of desired forms, \emph{i.e.},
+%   |p|, |TF|, |T| and |F|. The first three arguments come from splitting up
+%   the base form of the conditional, which gives the name, signature
+%   and a boolean to signal whether or not there was a colon in the
+%   name. In the absence of a colon, we throw an error and don't define
+%   any conditional. The fourth and fifth arguments build up the
+%   defining function.  The sixth is the parameters to use (possibly
+%   empty), the seventh is the list of forms to define, the eighth is the
+%   replacement text which we will augment when defining the forms.
+%   The use of \cs{tl_to_str:n} makes the later loop more robust.
+%
+%   A large number of our low-level conditionals look like \meta{code}
+%   \cs{prg_return_true:} \cs{else:} \cs{prg_return_false:} \cs{fi:} so
+%   we optimize this special case by calling
+%   \cs{@@_generate_conditional_fast:nw} \Arg{code}.  This passes
+%   \cs{use_i:nn} instead of \cs{use_i_ii:nnn} to functions such as
+%   \cs{@@_generate_p_form:wNNnnnnN}.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \@@_generate_conditional:nnNNNnnn #1#2#3#4#5#6#7#8
+  {
+    \if_meaning:w \c_false_bool #3
+      \msg_error:nne { kernel } { missing-colon }
+        { \token_to_str:c {#1} }
+      \exp_after:wN \use_none:nn
+    \fi:
+    \use:e
+      {
+        \exp_not:N \@@_generate_conditional:NNnnnnNw
+        \exp_not:n { #4 #5 {#1} {#2} {#6} }
+        \@@_generate_conditional_test:w
+          #8 \s_@@_mark
+            \@@_generate_conditional_fast:nw
+          \prg_return_true: \else: \prg_return_false: \fi: \s_@@_mark
+            \use_none:n
+        \exp_not:n { {#8} \use_i_ii:nnn }
+        \tl_to_str:n {#7}
+        \exp_not:n { , \q_@@_recursion_tail , \q_@@_recursion_stop }
+      }
+  }
+\cs_gset:Npn \@@_generate_conditional_test:w
+    #1 \prg_return_true: \else: \prg_return_false: \fi: \s_@@_mark #2
+  { #2 {#1} }
+\cs_gset:Npn \@@_generate_conditional_fast:nw #1#2 \exp_not:n #3
+  { \exp_not:n { {#1} \use_i:nn } }
+%    \end{macrocode}
+%   Looping through the list of desired forms.  First are six arguments
+%   and seventh is the form.  Use the form to call the
+%   correct type.  If the form does not exist, the \cs{use:c}
+%   construction results in \tn{relax}, and the error message is
+%   displayed (unless the form is empty, to allow for |{T, , F}|),
+%   then \cs{use_none:nnnnnnnn} cleans up.  Otherwise, the
+%   error message is removed by the variant form.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \@@_generate_conditional:NNnnnnNw #1#2#3#4#5#6#7#8 ,
+  {
+    \if_meaning:w \q_@@_recursion_tail #8
+      \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w
+    \fi:
+    \use:c { @@_generate_ #8 _form:wNNnnnnN }
+        \tl_if_empty:nF {#8}
+          {
+            \msg_error:nnee
+              { kernel } { conditional-form-unknown }
+              {#8} { \token_to_str:c { #3 : #4 } }
+          }
+        \use_none:nnnnnnnn
+      \s_@@_stop
+      #1 #2 {#3} {#4} {#5} {#6} #7
+    \@@_generate_conditional:NNnnnnNw #1 #2 {#3} {#4} {#5} {#6} #7
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \@@_generate_p_form:wNNnnnnN,
+%     \@@_generate_TF_form:wNNnnnnN,
+%     \@@_generate_T_form:wNNnnnnN,
+%     \@@_generate_F_form:wNNnnnnN
+%   }
+% \begin{macro}[EXP]{\@@_p_true:w, \@@_T_true:w, \@@_F_true:w, \@@_TF_true:w}
+%   How to generate the various forms. Those functions take the
+%   following arguments: 1: junk, 2: \cs{cs_set:Npn} or similar, 3: |p|
+%   (for protected conditionals) or |e|, 4: function name, 5: signature,
+%   6: parameter text, 7: replacement (possibly trimmed by
+%   \cs{@@_generate_conditional_fast:nw}), 8: \cs{use_i_ii:nnn} or
+%   \cs{use_i:nn} (for \enquote{fast} conditionals).  Remember that the
+%   logic-returning functions expect two arguments to be present after
+%   \cs{exp_end:}: notice the construction of the different variants
+%   relies on this, and that the |TF| and |F| variants will be slightly
+%   faster than the |T| version.  The |p| form is only valid for
+%   expandable tests, we check for that by making sure that the second
+%   argument is empty.  For \enquote{fast} conditionals, |#7| has an
+%   extra \cs[no-index]{if_\ldots{}}.  To optimize a bit further we
+%   don't use \cs{exp_after:wN} \cs{use_ii:nnn} and similar but instead use
+%   \cs{@@_TF_true:w} and similar to swap out the macro after \cs{fi:}. It would
+%   be a tiny bit faster if we directly grabbed the |T| and |F| arguments there,
+%   but if those are actually missing, the recovery from the runaway argument
+%   would not insert \cs{fi:} back, messing up nesting of conditionals.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \@@_generate_p_form:wNNnnnnN
+    #1 \s_@@_stop #2#3#4#5#6#7#8
+  {
+    \if_meaning:w e #3
+      \exp_after:wN \use_i:nn
+    \else:
+      \exp_after:wN \use_ii:nn
+    \fi:
+      {
+        #8
+          { \exp_args:Nc #2 { #4 _p: #5 } #6 }
+          { { #7 \exp_end: \c_true_bool \c_false_bool } }
+          { #7 \@@_p_true:w \fi: \c_false_bool }
+      }
+      {
+        \msg_error:nne { kernel } { protected-predicate }
+          { \token_to_str:c { #4 _p: #5 } }
+      }
+  }
+\cs_gset_protected:Npn \@@_generate_T_form:wNNnnnnN
+    #1 \s_@@_stop #2#3#4#5#6#7#8
+  {
+    #8
+      { \exp_args:Nc #2 { #4 : #5 T } #6 }
+      { { #7 \exp_end: \use:n \use_none:n } }
+      { #7 \@@_T_true:w \fi: \use_none:n }
+  }
+\cs_gset_protected:Npn \@@_generate_F_form:wNNnnnnN
+    #1 \s_@@_stop #2#3#4#5#6#7#8
+  {
+    #8
+      { \exp_args:Nc #2 { #4 : #5 F } #6 }
+      { { #7 \exp_end: { } } }
+      { #7 \@@_F_true:w \fi: \use:n }
+  }
+\cs_gset_protected:Npn \@@_generate_TF_form:wNNnnnnN
+    #1 \s_@@_stop #2#3#4#5#6#7#8
+  {
+    #8
+      { \exp_args:Nc #2 { #4 : #5 TF } #6 }
+      { { #7 \exp_end: } }
+      { #7 \@@_TF_true:w \fi: \use_ii:nn }
+  }
+\cs_gset:Npn \@@_p_true:w  \fi: \c_false_bool { \fi: \c_true_bool }
+\cs_gset:Npn \@@_T_true:w  \fi: \use_none:n   { \fi: \use:n }
+\cs_gset:Npn \@@_F_true:w  \fi: \use:n        { \fi: \use_none:n }
+\cs_gset:Npn \@@_TF_true:w \fi: \use_ii:nn    { \fi: \use_i:nn }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \prg_set_eq_conditional:NNn ,
+%     \prg_gset_eq_conditional:NNn,
+%     \prg_new_eq_conditional:NNn
+%   }
+% \begin{macro}{\@@_set_eq_conditional:NNNn}
+%   The setting-equal functions.  Split both functions and feed
+%   \Arg{name_1} \Arg{signature_1} \meta{boolean_1}
+%   \Arg{name_2} \Arg{signature_2} \meta{boolean_2}
+%   \meta{copying~function} \meta{conditions} |,| \cs{q_@@_recursion_tail}
+%   |,| \cs{q_@@_recursion_stop}
+%   to a first auxiliary.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \prg_set_eq_conditional:NNn
+  { \@@_set_eq_conditional:NNNn \cs_set_eq:cc }
+\cs_gset_protected:Npn \prg_gset_eq_conditional:NNn
+  { \@@_set_eq_conditional:NNNn \cs_gset_eq:cc }
+\cs_gset_protected:Npn \prg_new_eq_conditional:NNn
+  { \@@_set_eq_conditional:NNNn \cs_new_eq:cc }
+\cs_gset_protected:Npn \@@_set_eq_conditional:NNNn #1#2#3#4
+  {
+    \use:e
+      {
+        \exp_not:N \@@_set_eq_conditional:nnNnnNNw
+          \cs_split_function:N #2
+          \cs_split_function:N #3
+          \exp_not:N #1
+          \tl_to_str:n {#4}
+          \exp_not:n { , \q_@@_recursion_tail , \q_@@_recursion_stop }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \@@_set_eq_conditional:nnNnnNNw ,
+%     \@@_set_eq_conditional_loop:nnnnNw
+%   }
+% \begin{macro}[EXP]
+%   {
+%     \@@_set_eq_conditional_p_form:nnn  ,
+%     \@@_set_eq_conditional_TF_form:nnn ,
+%     \@@_set_eq_conditional_T_form:nnn  ,
+%     \@@_set_eq_conditional_F_form:nnn  ,
+%   }
+%   Split the function to be defined, and setup a manual clist loop over
+%   argument |#6| of the first auxiliary.  The second auxiliary receives
+%   twice three arguments coming from splitting the function to be
+%   defined and the function to copy.  Make sure that both functions
+%   contained a colon, otherwise we don't know how to build
+%   conditionals, hence abort.  Call the looping macro, with arguments
+%   \Arg{name_1} \Arg{signature_1} \Arg{name_2} \Arg{signature_2}
+%   \meta{copying~function} and followed by the comma list.  At each
+%   step in the loop, make sure that the conditional form we copy is
+%   defined, and copy it, otherwise abort.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \@@_set_eq_conditional:nnNnnNNw #1#2#3#4#5#6
+  {
+    \if_meaning:w \c_false_bool #3
+      \msg_error:nne { kernel } { missing-colon }
+        { \token_to_str:c {#1} }
+      \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w
+    \fi:
+    \if_meaning:w \c_false_bool #6
+      \msg_error:nne { kernel } { missing-colon }
+        { \token_to_str:c {#4} }
+      \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w
+    \fi:
+    \@@_set_eq_conditional_loop:nnnnNw {#1} {#2} {#4} {#5}
+  }
+\cs_gset_protected:Npn \@@_set_eq_conditional_loop:nnnnNw #1#2#3#4#5#6 ,
+  {
+    \if_meaning:w \q_@@_recursion_tail #6
+      \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w
+    \fi:
+    \use:c { @@_set_eq_conditional_ #6 _form:wNnnnn }
+        \tl_if_empty:nF {#6}
+          {
+            \msg_error:nnee
+              { kernel } { conditional-form-unknown }
+              {#6} { \token_to_str:c { #1 : #2 } }
+          }
+        \use_none:nnnnnn
+      \s_@@_stop
+      #5 {#1} {#2} {#3} {#4}
+    \@@_set_eq_conditional_loop:nnnnNw {#1} {#2} {#3} {#4} #5
+  }
+\cs_gset:Npn \@@_set_eq_conditional_p_form:wNnnnn #1 \s_@@_stop #2#3#4#5#6
+  { #2 { #3 _p : #4    }    { #5 _p : #6    } }
+\cs_gset:Npn \@@_set_eq_conditional_TF_form:wNnnnn #1 \s_@@_stop #2#3#4#5#6
+  { #2 { #3    : #4 TF }    { #5    : #6 TF } }
+\cs_gset:Npn \@@_set_eq_conditional_T_form:wNnnnn #1 \s_@@_stop #2#3#4#5#6
+  { #2 { #3    : #4 T  }    { #5    : #6 T  } }
+\cs_gset:Npn \@@_set_eq_conditional_F_form:wNnnnn #1 \s_@@_stop #2#3#4#5#6
+  { #2 { #3    : #4  F }    { #5    : #6  F } }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% All that is left is to define the canonical boolean true and false.
+% I think Michael originated the idea of expandable boolean tests.  At
+% first these were supposed to expand into either \texttt{TT} or
+% \texttt{TF} to be tested using \cs{if:w} but this was later changed to
+% |00| and |01|, so they could be used in logical
+% operations. Later again they were changed to being numerical
+% constants with values of $1$ for true and $0$ for false. We need
+% this from the get-go.
+%
+% \begin{variable}{\c_true_bool, \c_false_bool}
+%    Here are the canonical boolean values.
+%    \begin{macrocode}
+\tex_global:D \tex_chardef:D \c_true_bool  = 1 ~
+\tex_global:D \tex_chardef:D \c_false_bool = 0 ~
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Dissecting a control sequence}
+%
+%    \begin{macrocode}
+%<@@=cs>
+%    \end{macrocode}
+%
+% \begin{function}[EXP]{\@@_count_signature:N}
+%   \begin{syntax}
+%     \cs{@@_count_signature:N} \meta{function}
+%   \end{syntax}
+%   Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
+%   before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
+%   The \meta{number} of tokens in the \meta{signature} is then left in
+%   the input stream. If there was no \meta{signature} then the result is
+%   the marker value $-1$.
+% \end{function}
+%
+% \begin{function}{\@@_tmp:w}
+%   Function used for various short-term usages, for instance defining
+%   functions whose definition involves tokens which are hard to insert
+%   normally (spaces, characters with category other).
+% \end{function}
+%
+% \begin{macro}[EXP]{\cs_to_str:N}
+% \begin{macro}[EXP]{\@@_to_str:N, \@@_to_str:w}
+%   This converts a control sequence into the character string of its
+%   name, removing the leading escape character. This turns out to be
+%   a non-trivial matter as there a different cases:
+%   \begin{itemize}
+%     \item The usual case of a printable escape character;
+%     \item the case of a non-printable escape characters, e.g., when
+%     the value of the \tn{escapechar} is negative;
+%     \item when the escape character is a space.
+%   \end{itemize}
+%   One approach to solve this is to test how many tokens result from
+%   |\token_to_str:N \a|. If there are two tokens, then the escape
+%   character is printable, while if it is non-printable then only
+%   one is present.
+%
+%   However, there is an additional complication: the control
+%   sequence itself may start with a space. Clearly that should \emph{not} be
+%   lost in the process of converting to a string. So the approach adopted is
+%   a little more intricate still. When the escape character is printable,
+%   \verb*|\token_to_str:N \ | yields the escape character itself and a space.
+%   The character codes are different, thus the \cs{if:w} test is false,
+%   and \TeX{} reads \cs{@@_to_str:N} after turning the following
+%   control sequence into a string; this auxiliary removes the escape
+%   character, and stops the expansion of the initial \cs{tex_romannumeral:D}.
+%   The second case is that the escape character is not printable. Then
+%   the \cs{if:w} test is unfinished after reading a the space from
+%   \verb*|\token_to_str:N \ |, and the auxiliary \cs{@@_to_str:w}
+%   is expanded, feeding |-| as a second character for the test;
+%   the test is false, and \TeX{} skips to \cs{fi:}, then performs
+%   \cs{token_to_str:N}, and stops the \cs{tex_romannumeral:D} with \cs{c_zero_int}.
+%   The last case is that the escape character is itself a space. In this
+%   case, the \cs{if:w} test is true, and the auxiliary \cs{@@_to_str:w}
+%   comes into play, inserting |-\int_value:w|, which expands \cs{c_zero_int}
+%   to the character |0|. The initial \cs{tex_romannumeral:D} then sees
+%   |0|, which is not a terminated number, followed by the escape character,
+%   a space, which is removed, terminating the expansion of
+%   \cs{tex_romannumeral:D}.
+%   In all three cases, \cs{cs_to_str:N} takes two expansion steps
+%   to be fully expanded.
+%    \begin{macrocode}
+\cs_gset:Npn \cs_to_str:N
+  {
+%    \end{macrocode}
+%    We implement the expansion scheme using \cs{tex_romannumeral:D}
+%    terminating it with \cs{c_zero_int} rather than using \cs{exp:w} and
+%    \cs{exp_end:} as we normally do. The reason is that the code
+%    heavily depends on terminating the expansion with \cs{c_zero_int} so
+%    we make this dependency explicit.
+%    \begin{macrocode}
+    \tex_romannumeral:D
+      \if:w \token_to_str:N \ \@@_to_str:w \fi:
+      \exp_after:wN \@@_to_str:N \token_to_str:N
+  }
+\cs_gset:Npn \@@_to_str:N #1 { \c_zero_int }
+\cs_gset:Npn \@@_to_str:w #1 \@@_to_str:N
+  { - \int_value:w \fi: \exp_after:wN \c_zero_int }
+%    \end{macrocode}
+%   If speed is a concern we could use \tn{csstring} in \LuaTeX{}.  For
+%   the empty csname that primitive gives an empty result while the
+%   current \cs{cs_to_str:N} gives incorrect results in all engines
+%   (this is impossible to fix without huge performance hit).
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\cs_split_function:N}
+% \begin{macro}[EXP]
+%   {\@@_split_function_auxi:w, \@@_split_function_auxii:w}
+%   This function takes a function name and splits it into name with
+%   the escape char removed and argument specification. In addition to
+%   this, a third argument, a boolean \meta{true} or \meta{false} is
+%   returned with \meta{true} for when there is a colon in the function
+%   and \meta{false} if there is not.
+%
+%   First ensure that we actually get a properly evaluated string by
+%   expanding \cs{cs_to_str:N} twice.  If the function contained a
+%   colon, the auxiliary takes as |#1| the function name, delimited by
+%   the first colon, then the signature |#2|, delimited by \cs{s_@@_mark},
+%   then \cs{c_true_bool} as |#3|, and |#4| cleans up until \cs{s_@@_stop}.
+%   Otherwise, the |#1| contains the function name and \cs{s_@@_mark}
+%   \cs{c_true_bool}, |#2| is empty, |#3| is \cs{c_false_bool}, and |#4|
+%   cleans up.  The second
+%   auxiliary trims the trailing \cs{s_@@_mark} from the function name if
+%   present (that is, if the original function had no colon).
+%    \begin{macrocode}
+\cs_gset_protected:Npn \@@_tmp:w #1
+  {
+    \cs_gset:Npn \cs_split_function:N ##1
+      {
+        \exp_after:wN \exp_after:wN \exp_after:wN
+        \@@_split_function_auxi:w
+          \cs_to_str:N ##1 \s_@@_mark \c_true_bool
+          #1 \s_@@_mark \c_false_bool \s_@@_stop
+      }
+    \cs_gset:Npn \@@_split_function_auxi:w
+        ##1 #1 ##2 \s_@@_mark ##3##4 \s_@@_stop
+      { \@@_split_function_auxii:w ##1 \s_@@_mark \s_@@_stop {##2} ##3 }
+    \cs_gset:Npn \@@_split_function_auxii:w ##1 \s_@@_mark ##2 \s_@@_stop
+      { {##1} }
+  }
+\exp_after:wN \@@_tmp:w \token_to_str:N :
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Exist or free}
+%
+% A control sequence is said to \emph{exist} (to be used) if has an entry in
+% the hash table and its meaning is different from the primitive
+% \tn{relax} token. A control sequence is said to be \emph{free}
+% (to be defined) if it does not already exist.
+%
+% \begin{macro}[pTF, EXP]{\cs_if_exist:N, \cs_if_exist:c}
+% \begin{macro}{\@@_if_exist_c_aux:,\@@_if_exist_c_aux:w}
+%   Two versions for checking existence. For the |N| form we firstly
+%   check for \cs{scan_stop:} and then if it is in the hash
+%   table. There is no problem when inputting something like \cs{else:}
+%   or \cs{fi:} as \TeX{} will only ever skip input in case the token
+%   tested against is \cs{scan_stop:}.
+%
+%   In both the |N| and |c| form we use the way \cs{prg_set_conditional:Npnn}
+%   optimizes the conditionals to negate the tests using \cs{else:} (the
+%   \cs{else:} in the top level functions will be removed by the optimization,
+%   and this usage of \cs{else:} will be fine).
+%    \begin{macrocode}
+\prg_gset_conditional:Npnn \cs_if_exist:N #1 { p , T , F , TF }
+  {
+    \if_meaning:w #1 \scan_stop:
+      \use_i:nnnn
+    \else:
+    \fi:
+    \if_cs_exist:N #1
+      \prg_return_true:
+    \else:
+      \prg_return_false:
+    \fi:
+  }
+%    \end{macrocode}
+%   For the |c| form we firstly check if it is in the hash table and
+%   then for \cs{scan_stop:} so that we do not add it to the hash table
+%   unless it was already there. Here we have to be careful as the text
+%   to be skipped if the first test is false may contain tokens that
+%   disturb the scanner. Therefore, we ensure that the second test is
+%   performed after the first one has concluded completely.
+%    \begin{macrocode}
+\cs_if_exist:NTF \tex_lastnamedcs:D
+  {
+    \prg_gset_conditional:Npnn \cs_if_exist:c #1 { p , T , F , TF }
+      {
+        \if_cs_exist:w #1 \cs_end:
+          \@@_if_exist_c_aux:
+          \prg_return_true:
+        \else:
+          \prg_return_false:
+        \fi:
+      }
+    \cs_gset:Npn \@@_if_exist_c_aux:
+      { \fi: \exp_after:wN \if_meaning:w \tex_lastnamedcs:D \scan_stop: \else: }
+  }
+  {
+    \prg_gset_conditional:Npnn \cs_if_exist:c #1 { p , T , F , TF }
+      {
+        \if_cs_exist:w #1 \cs_end:
+          \@@_if_exist_c_aux:w
+        \fi:
+        \use_none:n {#1}
+        \if_false:
+          \prg_return_true:
+        \else:
+          \prg_return_false:
+        \fi:
+      }
+    \cs_gset:Npn \@@_if_exist_c_aux:w \fi: \use_none:n #1 \if_false:
+      { \fi: \exp_after:wN \if_meaning:w \cs:w #1 \cs_end: \scan_stop: \else: }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF, EXP]{\cs_if_free:N, \cs_if_free:c}
+%   The logical reversal of the above.
+%    \begin{macrocode}
+\prg_gset_conditional:Npnn \cs_if_free:N #1 { p , T , F , TF }
+  {
+    \if_cs_exist:N #1
+    \else:
+      \use_none:nnnn
+    \fi:
+    \if_meaning:w #1 \scan_stop:
+      \prg_return_true:
+    \else:
+      \prg_return_false:
+    \fi:
+  }
+\cs_if_exist:NTF \tex_lastnamedcs:D
+  {
+    \prg_gset_conditional:Npnn \cs_if_free:c #1 { p , T , F , TF }
+      {
+        \if_cs_exist:w #1 \cs_end:
+          \@@_if_free_c_aux:w
+        \fi:
+        \if_true:
+          \prg_return_true:
+        \else:
+          \prg_return_false:
+        \fi:
+      }
+    \cs_gset:Npn \@@_if_free_c_aux:w \fi: \if_true:
+      { \fi: \exp_after:wN \if_meaning:w \tex_lastnamedcs:D \scan_stop: }
+  }
+  {
+    \prg_gset_conditional:Npnn \cs_if_free:c #1 { p , T , F , TF }
+      {
+        \if_cs_exist:w #1 \cs_end:
+          \@@_if_free_c_aux:w
+        \fi:
+        \use_none:n {#1}
+        \if_true:
+          \prg_return_true:
+        \else:
+          \prg_return_false:
+        \fi:
+      }
+    \cs_gset:Npn \@@_if_free_c_aux:w \fi: \use_none:n #1 \if_true:
+      { \fi: \exp_after:wN \if_meaning:w \cs:w #1 \cs_end: \scan_stop: }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP,noTF,added=2011-10-10]
+%   {\cs_if_exist_use:N, \cs_if_exist_use:c}
+% \begin{macro}{\@@_if_exist_use_aux:w, \@@_if_exist_use_aux:Nnn}
+%   The \cs[index=cs_if_exist_use:N]{cs_if_exist_use:\ldots{}}
+%   functions cannot be implemented
+%   as conditionals because the true branch must leave both the control
+%   sequence itself and the true code in the input stream.
+%   For the \texttt{c} variants, we are careful not to put the control
+%   sequence in the hash table if it does not exist.
+%   If available we use the \tn{lastnamedcs} primitive.
+%    \begin{macrocode}
+\cs_gset:Npn \cs_if_exist_use:NTF #1#2
+  { \cs_if_exist:NTF #1 { #1 #2 } }
+\cs_gset:Npn \cs_if_exist_use:NF #1
+  { \cs_if_exist:NTF #1 #1 }
+\cs_gset:Npn \cs_if_exist_use:NT #1 #2
+  { \cs_if_exist:NT #1 { #1 #2 } }
+\cs_gset:Npn \cs_if_exist_use:N #1
+  { \cs_if_exist:NT #1 #1 }
+\cs_if_exist:NTF \tex_lastnamedcs:D
+  {
+    \cs_gset:Npn \cs_if_exist_use:cTF #1
+      {
+        \if_cs_exist:w #1 \cs_end:
+          \@@_if_exist_use_aux:w
+        \fi:
+        \use_ii:nn
+      }
+    \cs_gset:Npn \@@_if_exist_use_aux:w \fi: \use_ii:nn
+      { \fi: \exp_after:wN \@@_if_exist_use_aux:Nnn \tex_lastnamedcs:D }
+  }
+  {
+    \cs_gset:Npn \cs_if_exist_use:cTF #1
+      {
+        \if_cs_exist:w #1 \cs_end:
+          \@@_if_exist_use_aux:w
+        \fi:
+        \use_iii:nnn {#1}
+      }
+    \cs_gset:Npn \@@_if_exist_use_aux:w \fi: \use_iii:nnn #1
+      { \fi: \exp_after:wN \@@_if_exist_use_aux:Nnn \cs:w #1 \cs_end: }
+  }
+\cs_gset:Npn \@@_if_exist_use_aux:Nnn #1#2
+  {
+    \if_meaning:w #1 \scan_stop:
+      \exp_after:wN \use_iii:nnn
+    \fi:
+    \use_i:nn { #1 #2 }
+  }
+\cs_gset:Npn \cs_if_exist_use:cF #1
+  { \cs_if_exist_use:cTF {#1} {} }
+\cs_gset:Npn \cs_if_exist_use:cT #1#2
+  { \cs_if_exist_use:cTF {#1} {#2} {} }
+\cs_gset:Npn \cs_if_exist_use:c #1
+  { \cs_if_exist_use:cTF {#1} {} {} }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Preliminaries for new functions}
+%
+%    We provide two kinds of functions that can be used to define
+%    control sequences. On the one hand we have functions that check
+%    if their argument doesn't already exist, they are called
+%    |\..._new|. The second type of defining functions doesn't check
+%    if the argument is already defined.
+%
+%    Before we can define them, we need some auxiliary macros that allow
+%    us to generate error messages. The next few definitions here are
+%    only temporary, they will be redefined later on.
+%
+% \begin{macro}[documented-as = \msg_error:nnnn]
+%   {\msg_error:nnee, \msg_error:nne, \msg_error:nn}
+%   If an internal error occurs before \LaTeX3 has loaded \pkg{l3msg} then
+%   the code should issue a usable if terse error message and halt. This
+%   can only happen if a coding error is made by the team, so this is
+%   a reasonable response.  Setting the \tn{newlinechar} is needed, to
+%   turn |^^J| into a proper line break in plain \TeX{}.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \msg_error:nnee #1#2#3#4
+  {
+    \tex_newlinechar:D = `\^^J \scan_stop:
+    \tex_errmessage:D
+      {
+        !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~! ^^J
+        Argh,~internal~LaTeX3~error! ^^J ^^J
+        Module ~ #1 , ~ message~name~"#2": ^^J
+        Arguments~'#3'~and~'#4' ^^J ^^J
+        This~is~one~for~The~LaTeX3~Project:~bailing~out
+      }
+    \tex_end:D
+  }
+\cs_gset_protected:Npn \msg_error:nne #1#2#3
+  { \msg_error:nnee {#1} {#2} {#3} { } }
+\cs_gset_protected:Npn \msg_error:nn #1#2
+  { \msg_error:nnee {#1} {#2} { } { } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[rEXP]{\msg_line_context:}
+%   Another one from \pkg{l3msg} which will be altered later.
+%    \begin{macrocode}
+\cs_gset:Npn \msg_line_context:
+  { on~line~ \tex_the:D \tex_inputlineno:D }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[documented-as=\iow_log:n]{\iow_log:e, \iow_term:e}
+%    We define a routine to write only to the log file. And a
+%    similar one for writing to both the log file and the terminal.
+%    These will be redefined later by \pkg{l3file}.
+%    \begin{macrocode}
+\cs_gset_protected:Npn \iow_log:e
+  { \tex_immediate:D \tex_write:D -1 }
+\cs_gset_protected:Npn \iow_term:e
+  { \tex_immediate:D \tex_write:D 16 }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\__kernel_chk_if_free_cs:N, \__kernel_chk_if_free_cs:c}
+%   This command is called by \cs{cs_new_nopar:Npn} and \cs{cs_new_eq:NN}
+%   \emph{etc.}\
+%   to make sure that the argument sequence is not already in use. If
+%   it is, an error is signalled.  It checks if \meta{csname} is
+%   undefined or \cs{scan_stop:}. Otherwise an error message is
+%   issued. We have to make sure we don't put the argument into the
+%   conditional processing since it may be an |\if...| type function!
+%    \begin{macrocode}
+\cs_gset_protected:Npn \__kernel_chk_if_free_cs:N #1
+  {
+    \cs_if_free:NF #1
+      {
+        \msg_error:nnee { kernel } { command-already-defined }
+          { \token_to_str:N #1 } { \token_to_meaning:N #1 }
+      }
+  }
+\cs_gset_protected:Npn \__kernel_chk_if_free_cs:c
+  { \exp_args:Nc \__kernel_chk_if_free_cs:N }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Defining new functions}
+%
+%    \begin{macrocode}
+%<@@=cs>
+%    \end{macrocode}
+%
+% \begin{macro}
+%   {
+%     \cs_new_nopar:Npn           , \cs_new_nopar:Npe           , \cs_new_nopar:Npx           ,
+%     \cs_new:Npn                 , \cs_new:Npe                 , \cs_new:Npx                 ,
+%     \cs_new_protected_nopar:Npn , \cs_new_protected_nopar:Npe , \cs_new_protected_nopar:Npx ,
+%     \cs_new_protected:Npn       , \cs_new_protected:Npe       , \cs_new_protected:Npx
+%   }
+% \begin{macro}{\@@_tmp:w}
+%   Function which check that the control sequence is free before
+%   defining it.
+%     \begin{macrocode}
+\cs_set:Npn \@@_tmp:w #1#2
+  {
+    \cs_gset_protected:Npn #1 ##1
+      {
+        \__kernel_chk_if_free_cs:N ##1
+        #2 ##1
+      }
+  }
+\@@_tmp:w \cs_new_nopar:Npn           \cs_gset_nopar:Npn
+\@@_tmp:w \cs_new_nopar:Npe           \cs_gset_nopar:Npe
+\@@_tmp:w \cs_new_nopar:Npx           \cs_gset_nopar:Npx
+\@@_tmp:w \cs_new:Npn                 \cs_gset:Npn
+\@@_tmp:w \cs_new:Npe                 \cs_gset:Npe
+\@@_tmp:w \cs_new:Npx                 \cs_gset:Npx
+\@@_tmp:w \cs_new_protected_nopar:Npn \cs_gset_protected_nopar:Npn
+\@@_tmp:w \cs_new_protected_nopar:Npe \cs_gset_protected_nopar:Npe
+\@@_tmp:w \cs_new_protected_nopar:Npx \cs_gset_protected_nopar:Npx
+\@@_tmp:w \cs_new_protected:Npn       \cs_gset_protected:Npn
+\@@_tmp:w \cs_new_protected:Npe       \cs_gset_protected:Npe
+\@@_tmp:w \cs_new_protected:Npx       \cs_gset_protected:Npx
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[documented-as=\cs_set_nopar:Npn]
+%   {
+%     \cs_set_nopar:cpn  , \cs_set_nopar:cpe  , \cs_set_nopar:cpx  ,
+%     \cs_gset_nopar:cpn , \cs_gset_nopar:cpe , \cs_gset_nopar:cpx ,
+%     \cs_new_nopar:cpn  , \cs_new_nopar:cpe  , \cs_new_nopar:cpx
+%   }
+%   Like \cs{cs_set_nopar:Npn} and \cs{cs_new_nopar:Npn}, except that the
+%   first argument consists of the sequence of characters that should
+%   be used to form the name of the desired control sequence (the |c|
+%   stands for csname argument, see the expansion module). Global
+%   versions are also provided.
+%
+%   \cs{cs_set_nopar:cpn}\meta{string}\meta{rep-text} turns \meta{string}
+%   into a csname and then assigns \meta{rep-text} to it by using
+%   \cs{cs_set_nopar:Npn}.  This means that there might be a parameter
+%   string between the two arguments.
+%    \begin{macrocode}
+\cs_set:Npn \@@_tmp:w #1#2
+  { \cs_new_protected_nopar:Npn #1 { \exp_args:Nc #2 } }
+\@@_tmp:w \cs_set_nopar:cpn  \cs_set_nopar:Npn
+\@@_tmp:w \cs_set_nopar:cpe  \cs_set_nopar:Npe
+\@@_tmp:w \cs_set_nopar:cpx  \cs_set_nopar:Npx
+\@@_tmp:w \cs_gset_nopar:cpn \cs_gset_nopar:Npn
+\@@_tmp:w \cs_gset_nopar:cpe \cs_gset_nopar:Npe
+\@@_tmp:w \cs_gset_nopar:cpx \cs_gset_nopar:Npx
+\@@_tmp:w \cs_new_nopar:cpn  \cs_new_nopar:Npn
+\@@_tmp:w \cs_new_nopar:cpe  \cs_new_nopar:Npe
+\@@_tmp:w \cs_new_nopar:cpx  \cs_new_nopar:Npx
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[documented-as=\cs_set:Npn]
+%   {
+%     \cs_set:cpn  , \cs_set:cpe  , \cs_set:cpx  ,
+%     \cs_gset:cpn , \cs_gset:cpe , \cs_gset:cpx ,
+%     \cs_new:cpn  , \cs_new:cpe  , \cs_new:cpx
+%   }
+%   Variants of the \cs{cs_set:Npn} versions which make a csname out
+%   of the first arguments. We may also do this globally.
+%    \begin{macrocode}
+\@@_tmp:w \cs_set:cpn  \cs_set:Npn
+\@@_tmp:w \cs_set:cpe  \cs_set:Npe
+\@@_tmp:w \cs_set:cpx  \cs_set:Npx
+\@@_tmp:w \cs_gset:cpn \cs_gset:Npn
+\@@_tmp:w \cs_gset:cpe \cs_gset:Npe
+\@@_tmp:w \cs_gset:cpx \cs_gset:Npx
+\@@_tmp:w \cs_new:cpn  \cs_new:Npn
+\@@_tmp:w \cs_new:cpe  \cs_new:Npe
+\@@_tmp:w \cs_new:cpx  \cs_new:Npx
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[documented-as=\cs_set_protected_nopar:Npn]
+%   {
+%     \cs_set_protected_nopar:cpn  , \cs_set_protected_nopar:cpe  , \cs_set_protected_nopar:cpx  ,
+%     \cs_gset_protected_nopar:cpn , \cs_gset_protected_nopar:cpe , \cs_gset_protected_nopar:cpx ,
+%     \cs_new_protected_nopar:cpn  , \cs_new_protected_nopar:cpe  , \cs_new_protected_nopar:cpx
+%   }
+%   Variants of the \cs{cs_set_protected_nopar:Npn} versions which make
+%   a csname out of the first arguments. We may also do this globally.
+%    \begin{macrocode}
+\@@_tmp:w \cs_set_protected_nopar:cpn  \cs_set_protected_nopar:Npn
+\@@_tmp:w \cs_set_protected_nopar:cpe  \cs_set_protected_nopar:Npe
+\@@_tmp:w \cs_set_protected_nopar:cpx  \cs_set_protected_nopar:Npx
+\@@_tmp:w \cs_gset_protected_nopar:cpn \cs_gset_protected_nopar:Npn
+\@@_tmp:w \cs_gset_protected_nopar:cpe \cs_gset_protected_nopar:Npe
+\@@_tmp:w \cs_gset_protected_nopar:cpx \cs_gset_protected_nopar:Npx
+\@@_tmp:w \cs_new_protected_nopar:cpn  \cs_new_protected_nopar:Npn
+\@@_tmp:w \cs_new_protected_nopar:cpe  \cs_new_protected_nopar:Npe
+\@@_tmp:w \cs_new_protected_nopar:cpx  \cs_new_protected_nopar:Npx
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[documented-as=\cs_set_protected:Npn]
+%   {
+%     \cs_set_protected:cpn  , \cs_set_protected:cpe  , \cs_set_protected:cpx  ,
+%     \cs_gset_protected:cpn , \cs_gset_protected:cpe , \cs_gset_protected:cpx ,
+%     \cs_new_protected:cpn  , \cs_new_protected:cpe  , \cs_new_protected:cpx
+%   }
+%   Variants of the \cs{cs_set_protected:Npn} versions which make a csname
+%   out of the first arguments. We may also do this globally.
+%    \begin{macrocode}
+\@@_tmp:w \cs_set_protected:cpn  \cs_set_protected:Npn
+\@@_tmp:w \cs_set_protected:cpe  \cs_set_protected:Npe
+\@@_tmp:w \cs_set_protected:cpx  \cs_set_protected:Npx
+\@@_tmp:w \cs_gset_protected:cpn \cs_gset_protected:Npn
+\@@_tmp:w \cs_gset_protected:cpe \cs_gset_protected:Npe
+\@@_tmp:w \cs_gset_protected:cpx \cs_gset_protected:Npx
+\@@_tmp:w \cs_new_protected:cpn  \cs_new_protected:Npn
+\@@_tmp:w \cs_new_protected:cpe  \cs_new_protected:Npe
+\@@_tmp:w \cs_new_protected:cpx  \cs_new_protected:Npx
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Copying definitions}
+%
+% \begin{macro}
+%   {
+%     \cs_set_eq:NN  , \cs_set_eq:cN  , \cs_set_eq:Nc  , \cs_set_eq:cc  ,
+%     \cs_gset_eq:NN , \cs_gset_eq:cN , \cs_gset_eq:Nc , \cs_gset_eq:cc ,
+%     \cs_new_eq:NN  , \cs_new_eq:cN  , \cs_new_eq:Nc  , \cs_new_eq:cc
+%   }
+%   These macros allow us to copy the definition of a control sequence
+%   to another control sequence.
+%
+%   The |=| sign allows us to define funny char tokens like |=| itself
+%   or \verb*| | with this function. For the definition of
+%   |\c_space_char{~}| to work we need the |~| after the |=|.
+%
+%   \cs{cs_set_eq:NN} is long to avoid problems with a literal argument
+%   of \cs{par}.  While \cs{cs_new_eq:NN} will probably never be correct
+%   with a first argument of \cs{par}, define it long in order to throw
+%   an \enquote{already defined} error rather than
+%   \enquote{runaway argument}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cs_set_eq:NN #1 { \tex_let:D #1 =~ }
+\cs_new_protected:Npn \cs_set_eq:cN { \exp_args:Nc  \cs_set_eq:NN }
+\cs_new_protected:Npn \cs_set_eq:Nc { \exp_args:NNc \cs_set_eq:NN }
+\cs_new_protected:Npn \cs_set_eq:cc { \exp_args:Ncc \cs_set_eq:NN }
+\cs_new_protected:Npn \cs_gset_eq:NN { \tex_global:D  \cs_set_eq:NN }
+\cs_new_protected:Npn \cs_gset_eq:Nc { \exp_args:NNc  \cs_gset_eq:NN }
+\cs_new_protected:Npn \cs_gset_eq:cN { \exp_args:Nc   \cs_gset_eq:NN }
+\cs_new_protected:Npn \cs_gset_eq:cc { \exp_args:Ncc  \cs_gset_eq:NN }
+\cs_new_protected:Npn \cs_new_eq:NN #1
+  {
+    \__kernel_chk_if_free_cs:N #1
+    \tex_global:D \cs_set_eq:NN #1
+  }
+\cs_new_protected:Npn \cs_new_eq:cN { \exp_args:Nc  \cs_new_eq:NN }
+\cs_new_protected:Npn \cs_new_eq:Nc { \exp_args:NNc \cs_new_eq:NN }
+\cs_new_protected:Npn \cs_new_eq:cc { \exp_args:Ncc \cs_new_eq:NN }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Undefining functions}
+%
+% \begin{macro}{\cs_undefine:N, \cs_undefine:c}
+%   The following function is used to free the main memory from the
+%   definition of some function that isn't in use any longer.
+%   The \texttt{c} variant is careful not to add the control sequence
+%   to the hash table if it isn't there yet, and it also avoids nesting
+%   \TeX{} conditionals in case |#1| is unbalanced in this matter.
+%   We optimize the case where the command exists by reducing as much as
+%   possible the tokens in the conditional.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cs_undefine:N #1
+  { \cs_gset_eq:NN #1 \tex_undefined:D }
+\cs_new_protected:Npn \cs_undefine:c #1
+  {
+    \if_cs_exist:w #1 \cs_end:
+    \else:
+      \use_i:nnnn
+    \fi:
+    \exp_args:Nc \cs_undefine:N {#1}
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Generating parameter text from argument count}
+%
+%    \begin{macrocode}
+%<@@=cs>
+%    \end{macrocode}
+%
+% \begin{macro}{\__kernel_cs_parm_from_arg_count:nnF}
+% \begin{macro}{\@@_parm_from_arg_count_test:nnF}
+%   \LaTeX3 provides shorthands to define control sequences and
+%   conditionals with a simple parameter text, derived directly from the
+%   signature, or more generally from knowing the number of arguments,
+%   between~$0$ and~$9$.  This function expands to its first argument,
+%   untouched, followed by a brace group containing the parameter text
+%   |{#|$1$\ldots{}|#|$n$|}|, where $n$ is the result of evaluating the
+%   second argument (as described in \cs{int_eval:n}).  If the second
+%   argument gives a result outside the range $[0,9]$, the third
+%   argument is returned instead, normally an error message.  Some of
+%   the functions use here are not defined yet, but will be defined
+%   before this function is called.
+%    \begin{macrocode}
+\cs_new_protected:Npn \__kernel_cs_parm_from_arg_count:nnF #1#2
+  {
+    \exp_args:Ne \@@_parm_from_arg_count_test:nnF
+      {
+        \exp_after:wN \exp_not:n
+        \if_case:w \int_eval:n {#2}
+             { }
+        \or: { ##1 }
+        \or: { ##1##2 }
+        \or: { ##1##2##3 }
+        \or: { ##1##2##3##4 }
+        \or: { ##1##2##3##4##5 }
+        \or: { ##1##2##3##4##5##6 }
+        \or: { ##1##2##3##4##5##6##7 }
+        \or: { ##1##2##3##4##5##6##7##8 }
+        \or: { ##1##2##3##4##5##6##7##8##9 }
+        \else: { \c_false_bool }
+        \fi:
+      }
+      {#1}
+  }
+\cs_new_protected:Npn \@@_parm_from_arg_count_test:nnF #1#2
+  {
+    \if_meaning:w \c_false_bool #1
+      \exp_after:wN \use_ii:nn
+    \else:
+      \exp_after:wN \use_i:nn
+    \fi:
+    { #2 {#1} }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Defining functions from a given number of arguments}
+%
+%    \begin{macrocode}
+%<@@=cs>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP]{\@@_count_signature:N, \@@_count_signature:c}
+% \begin{macro}[EXP]{\@@_count_signature:n}
+% \begin{macro}[EXP]{\@@_count_signature:nnN}
+%   Counting the number of tokens in the signature, \emph{i.e.}, the
+%   number of arguments the function should take.  Since this is not
+%   used in any time-critical function, we simply use \cs{tl_count:n} if
+%   there is a signature, otherwise $-1$ arguments to signal an error.
+%   We need a variant form right away.
+%    \begin{macrocode}
+\cs_new:Npn \@@_count_signature:N #1
+  { \exp_args:Nf \@@_count_signature:n { \cs_split_function:N #1 } }
+\cs_new:Npn \@@_count_signature:n #1
+  { \int_eval:n { \@@_count_signature:nnN #1 } }
+\cs_new:Npn \@@_count_signature:nnN #1#2#3
+  {
+    \if_meaning:w \c_true_bool #3
+      \tl_count:n {#2}
+    \else:
+      -1
+    \fi:
+  }
+\cs_new:Npn \@@_count_signature:c
+  { \exp_args:Nc \@@_count_signature:N }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \cs_generate_from_arg_count:NNnn,
+%     \cs_generate_from_arg_count:cNnn,
+%     \cs_generate_from_arg_count:Ncnn
+%   }
+%   We provide a constructor function for defining functions with a
+%   given number of arguments.  For this we need to choose the correct
+%   parameter text and then use that when defining.  Since \TeX{}
+%   supports from zero to nine arguments, we use a simple switch to
+%   choose the correct parameter text, ensuring the result is returned
+%   after finishing the conditional.  If it is not between zero and
+%   nine, we throw an error.
+%
+%   1: function to define, 2: with what to define it, 3: the number of
+%   args it requires and 4: the replacement text
+%    \begin{macrocode}
+\cs_new_protected:Npn \cs_generate_from_arg_count:NNnn #1#2#3#4
+  {
+    \__kernel_cs_parm_from_arg_count:nnF { \use:nnn #2 #1 } {#3}
+      {
+        \msg_error:nnee { kernel } { bad-number-of-arguments }
+          { \token_to_str:N #1 } { \int_eval:n {#3} }
+        \use_none:n
+      }
+      {#4}
+  }
+%    \end{macrocode}
+%   A variant form we need right away, plus one which is used elsewhere but
+%   which is most logically created here.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cs_generate_from_arg_count:cNnn
+  { \exp_args:Nc \cs_generate_from_arg_count:NNnn }
+\cs_new_protected:Npn \cs_generate_from_arg_count:Ncnn
+  { \exp_args:NNc \cs_generate_from_arg_count:NNnn }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Using the signature to define functions}
+%
+%    \begin{macrocode}
+%<@@=cs>
+%    \end{macrocode}
+%
+% We can now combine some of the tools we have to provide a simple
+% interface for defining functions, where the number of arguments is
+% read from the signature.  For instance,
+% |\cs_set:Nn \foo_bar:nn {#1,#2}|.
+%
+% \begin{macro}
+%   {
+%     \cs_set:Nn                  , \cs_set:Ne                  , \cs_set:Nx                  ,
+%     \cs_set_nopar:Nn            , \cs_set_nopar:Ne            , \cs_set_nopar:Nx            ,
+%     \cs_set_protected:Nn        , \cs_set_protected:Ne        , \cs_set_protected:Nx        ,
+%     \cs_set_protected_nopar:Nn  , \cs_set_protected_nopar:Ne  , \cs_set_protected_nopar:Nx  ,
+%     \cs_gset:Nn                 , \cs_gset:Ne                 , \cs_gset:Nx                 ,
+%     \cs_gset_nopar:Nn           , \cs_gset_nopar:Ne           , \cs_gset_nopar:Nx           ,
+%     \cs_gset_protected:Nn       , \cs_gset_protected:Ne       , \cs_gset_protected:Nx       ,
+%     \cs_gset_protected_nopar:Nn , \cs_gset_protected_nopar:Ne , \cs_gset_protected_nopar:Nx ,
+%     \cs_new:Nn                  , \cs_new:Ne                  , \cs_new:Nx                  ,
+%     \cs_new_nopar:Nn            , \cs_new_nopar:Ne            , \cs_new_nopar:Nx            ,
+%     \cs_new_protected:Nn        , \cs_new_protected:Ne        , \cs_new_protected:Nx        ,
+%     \cs_new_protected_nopar:Nn  , \cs_new_protected_nopar:Ne  , \cs_new_protected_nopar:Nx  ,
+%   }
+%   We want to define \cs{cs_set:Nn} as
+%   \begin{verbatim}
+%     \cs_set_protected:Npn \cs_set:Nn #1#2
+%       {
+%         \cs_generate_from_arg_count:NNnn #1 \cs_set:Npn
+%           { \@@_count_signature:N #1 } {#2}
+%       }
+%   \end{verbatim}
+%   In short, to define \cs{cs_set:Nn} we need just use \cs{cs_set:Npn},
+%   everything else is the same for each variant.  Therefore, we can
+%   make it simpler by temporarily defining a function to do this for
+%   us.
+%    \begin{macrocode}
+\cs_set:Npn \@@_tmp:w #1#2#3
+  {
+    \cs_new_protected:cpx { cs_ #1 : #2 }
+      {
+        \exp_not:N \@@_generate_from_signature:NNn
+        \exp_after:wN \exp_not:N \cs:w cs_ #1 : #3 \cs_end:
+      }
+  }
+\cs_new_protected:Npn \@@_generate_from_signature:NNn #1#2
+  {
+    \use:e
+      {
+        \@@_generate_from_signature:nnNNNn
+        \cs_split_function:N #2
+      }
+      #1 #2
+  }
+\cs_new_protected:Npn \@@_generate_from_signature:nnNNNn #1#2#3#4#5#6
+  {
+    \bool_if:NTF #3
+      {
+        \cs_set_nopar:Npx \@@_tmp:w
+          { \tl_map_function:nN {#2} \@@_generate_from_signature:n }
+        \tl_if_empty:oF \@@_tmp:w
+          {
+            \msg_error:nneee { kernel } { non-base-function }
+              { \token_to_str:N #5 } {#2} { \@@_tmp:w }
+          }
+        \cs_generate_from_arg_count:NNnn
+          #5 #4 { \tl_count:n {#2} } {#6}
+      }
+      {
+        \msg_error:nne { kernel } { missing-colon }
+          { \token_to_str:N #5 }
+      }
+  }
+\cs_new:Npn \@@_generate_from_signature:n #1
+  {
+    \if:w n #1 \else: \if:w N #1 \else:
+    \if:w T #1 \else: \if:w F #1 \else: #1 \fi: \fi: \fi: \fi:
+  }
+%    \end{macrocode}
+%   Then we define the 24 variants beginning with |N|.
+%    \begin{macrocode}
+\@@_tmp:w { set }                  { Nn } { Npn }
+\@@_tmp:w { set }                  { Ne } { Npe }
+\@@_tmp:w { set }                  { Nx } { Npx }
+\@@_tmp:w { set_nopar }            { Nn } { Npn }
+\@@_tmp:w { set_nopar }            { Ne } { Npe }
+\@@_tmp:w { set_nopar }            { Nx } { Npx }
+\@@_tmp:w { set_protected }        { Nn } { Npn }
+\@@_tmp:w { set_protected }        { Ne } { Npe }
+\@@_tmp:w { set_protected }        { Nx } { Npx }
+\@@_tmp:w { set_protected_nopar }  { Nn } { Npn }
+\@@_tmp:w { set_protected_nopar }  { Ne } { Npe }
+\@@_tmp:w { set_protected_nopar }  { Nx } { Npx }
+\@@_tmp:w { gset }                 { Nn } { Npn }
+\@@_tmp:w { gset }                 { Ne } { Npe }
+\@@_tmp:w { gset }                 { Nx } { Npx }
+\@@_tmp:w { gset_nopar }           { Nn } { Npn }
+\@@_tmp:w { gset_nopar }           { Ne } { Npe }
+\@@_tmp:w { gset_nopar }           { Nx } { Npx }
+\@@_tmp:w { gset_protected }       { Nn } { Npn }
+\@@_tmp:w { gset_protected }       { Ne } { Npe }
+\@@_tmp:w { gset_protected }       { Nx } { Npx }
+\@@_tmp:w { gset_protected_nopar } { Nn } { Npn }
+\@@_tmp:w { gset_protected_nopar } { Ne } { Npe }
+\@@_tmp:w { gset_protected_nopar } { Nx } { Npx }
+\@@_tmp:w { new }                  { Nn } { Npn }
+\@@_tmp:w { new }                  { Ne } { Npe }
+\@@_tmp:w { new }                  { Nx } { Npx }
+\@@_tmp:w { new_nopar }            { Nn } { Npn }
+\@@_tmp:w { new_nopar }            { Ne } { Npe }
+\@@_tmp:w { new_nopar }            { Nx } { Npx }
+\@@_tmp:w { new_protected }        { Nn } { Npn }
+\@@_tmp:w { new_protected }        { Ne } { Npe }
+\@@_tmp:w { new_protected }        { Nx } { Npx }
+\@@_tmp:w { new_protected_nopar }  { Nn } { Npn }
+\@@_tmp:w { new_protected_nopar }  { Ne } { Npe }
+\@@_tmp:w { new_protected_nopar }  { Nx } { Npx }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[documented-as=\cs_set:Nn]
+%   {
+%     \cs_set:cn                  , \cs_set:ce                  , \cs_set:cx                  ,
+%     \cs_set_nopar:cn            , \cs_set_nopar:ce            , \cs_set_nopar:cx            ,
+%     \cs_set_protected:cn        , \cs_set_protected:ce        , \cs_set_protected:cx        ,
+%     \cs_set_protected_nopar:cn  , \cs_set_protected_nopar:ce  , \cs_set_protected_nopar:cx  ,
+%     \cs_gset:cn                 , \cs_gset:ce                 , \cs_gset:cx                 ,
+%     \cs_gset_nopar:cn           , \cs_gset_nopar:ce           , \cs_gset_nopar:cx           ,
+%     \cs_gset_protected:cn       , \cs_gset_protected:ce       , \cs_gset_protected:cx       ,
+%     \cs_gset_protected_nopar:cn , \cs_gset_protected_nopar:ce , \cs_gset_protected_nopar:cx ,
+%     \cs_new:cn                  , \cs_new:ce                  , \cs_new:cx                  ,
+%     \cs_new_nopar:cn            , \cs_new_nopar:ce            , \cs_new_nopar:cx            ,
+%     \cs_new_protected:cn        , \cs_new_protected:ce        , \cs_new_protected:cx        ,
+%     \cs_new_protected_nopar:cn  , \cs_new_protected_nopar:ce  , \cs_new_protected_nopar:cx  ,
+%   }
+%   The 24 |c| variants simply use \cs{exp_args:Nc}.
+%    \begin{macrocode}
+\cs_set:Npn \@@_tmp:w #1#2
+  {
+    \cs_new_protected:cpx { cs_ #1 : c #2 }
+      {
+        \exp_not:N \exp_args:Nc
+        \exp_after:wN \exp_not:N \cs:w cs_ #1 : N #2 \cs_end:
+      }
+  }
+\@@_tmp:w { set }                  { n }
+\@@_tmp:w { set }                  { e }
+\@@_tmp:w { set }                  { x }
+\@@_tmp:w { set_nopar }            { n }
+\@@_tmp:w { set_nopar }            { e }
+\@@_tmp:w { set_nopar }            { x }
+\@@_tmp:w { set_protected }        { n }
+\@@_tmp:w { set_protected }        { e }
+\@@_tmp:w { set_protected }        { x }
+\@@_tmp:w { set_protected_nopar }  { n }
+\@@_tmp:w { set_protected_nopar }  { e }
+\@@_tmp:w { set_protected_nopar }  { x }
+\@@_tmp:w { gset }                 { n }
+\@@_tmp:w { gset }                 { e }
+\@@_tmp:w { gset }                 { x }
+\@@_tmp:w { gset_nopar }           { n }
+\@@_tmp:w { gset_nopar }           { e }
+\@@_tmp:w { gset_nopar }           { x }
+\@@_tmp:w { gset_protected }       { n }
+\@@_tmp:w { gset_protected }       { e }
+\@@_tmp:w { gset_protected }       { x }
+\@@_tmp:w { gset_protected_nopar } { n }
+\@@_tmp:w { gset_protected_nopar } { e }
+\@@_tmp:w { gset_protected_nopar } { x }
+\@@_tmp:w { new }                  { n }
+\@@_tmp:w { new }                  { e }
+\@@_tmp:w { new }                  { x }
+\@@_tmp:w { new_nopar }            { n }
+\@@_tmp:w { new_nopar }            { e }
+\@@_tmp:w { new_nopar }            { x }
+\@@_tmp:w { new_protected }        { n }
+\@@_tmp:w { new_protected }        { e }
+\@@_tmp:w { new_protected }        { x }
+\@@_tmp:w { new_protected_nopar }  { n }
+\@@_tmp:w { new_protected_nopar }  { e }
+\@@_tmp:w { new_protected_nopar }  { x }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Checking control sequence equality}
+%
+% \begin{macro}[pTF, EXP]
+%   {\cs_if_eq:NN, \cs_if_eq:cN, \cs_if_eq:Nc, \cs_if_eq:cc}
+%   Check if two control sequences are identical.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \cs_if_eq:NN #1#2 { p , T , F , TF }
+  {
+    \if_meaning:w #1#2
+      \prg_return_true: \else: \prg_return_false: \fi:
+  }
+\cs_new:Npn \cs_if_eq_p:cN { \exp_args:Nc  \cs_if_eq_p:NN }
+\cs_new:Npn \cs_if_eq:cNTF { \exp_args:Nc  \cs_if_eq:NNTF }
+\cs_new:Npn \cs_if_eq:cNT  { \exp_args:Nc  \cs_if_eq:NNT }
+\cs_new:Npn \cs_if_eq:cNF  { \exp_args:Nc  \cs_if_eq:NNF }
+\cs_new:Npn \cs_if_eq_p:Nc { \exp_args:NNc \cs_if_eq_p:NN }
+\cs_new:Npn \cs_if_eq:NcTF { \exp_args:NNc \cs_if_eq:NNTF }
+\cs_new:Npn \cs_if_eq:NcT  { \exp_args:NNc \cs_if_eq:NNT }
+\cs_new:Npn \cs_if_eq:NcF  { \exp_args:NNc \cs_if_eq:NNF }
+\cs_new:Npn \cs_if_eq_p:cc { \exp_args:Ncc \cs_if_eq_p:NN }
+\cs_new:Npn \cs_if_eq:ccTF { \exp_args:Ncc \cs_if_eq:NNTF }
+\cs_new:Npn \cs_if_eq:ccT  { \exp_args:Ncc \cs_if_eq:NNT }
+\cs_new:Npn \cs_if_eq:ccF  { \exp_args:Ncc \cs_if_eq:NNF }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Diagnostic functions}
+%
+%    \begin{macrocode}
+%<@@=kernel>
+%    \end{macrocode}
+%
+% \begin{macro}{\@@_chk_defined:NT}
+%   Error if the variable |#1| is not defined.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_chk_defined:NT #1#2
+  {
+    \cs_if_exist:NTF #1
+      {#2}
+      {
+        \msg_error:nne { kernel } { variable-not-defined }
+          { \token_to_str:N #1 }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {\@@_register_show:N, \@@_register_show:c, \@@_register_log:N, \@@_register_log:c}
+% \begin{macro}{\@@_register_show_aux:NN, \@@_register_show_aux:nNN}
+%   Simply using the \tn{showthe} primitive does not allow for
+%   line-wrapping, so instead use \cs{tl_show:n} and \cs{tl_log:n} (defined
+%   in \pkg{l3tl} and that performs line-wrapping).  This displays
+%   |>~|\meta{variable}|=|\meta{value}.  We expand the value before-hand
+%   as otherwise some integers (such as \tn{currentgrouplevel} or
+%   \tn{currentgrouptype}) altered by the line-wrapping code would show
+%   wrong values.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_register_show:N
+  { \@@_register_show_aux:NN \tl_show:n }
+\cs_new_protected:Npn \@@_register_show:c
+  { \exp_args:Nc \@@_register_show:N }
+\cs_new_protected:Npn \@@_register_log:N
+  { \@@_register_show_aux:NN \tl_log:n }
+\cs_new_protected:Npn \@@_register_log:c
+  { \exp_args:Nc \@@_register_log:N }
+\cs_new_protected:Npn \@@_register_show_aux:NN #1#2
+  {
+    \@@_chk_defined:NT #2
+      {
+        \exp_args:No \@@_register_show_aux:nNN
+          { \tex_the:D #2 } #2 #1
+      }
+  }
+\cs_new_protected:Npn \@@_register_show_aux:nNN #1#2#3
+  { \exp_args:No #3 { \token_to_str:N #2 = #1 } }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\cs_show:N, \cs_show:c, \cs_log:N, \cs_log:c, \@@_show:NN}
+%   Some control sequences have a very long name or meaning.  Thus,
+%   simply using \TeX{}'s primitive \tn{show} could lead to overlong
+%   lines.  The output of this primitive is mimicked to some extent,
+%   then the re-built string is given to \cs{tl_show:n} or \cs{tl_log:n} for
+%   line-wrapping.  We must expand the meaning before passing it to the
+%   wrapping code as otherwise we would wrongly see the definitions that
+%   are in place there.  To get correct escape characters, set the
+%   \tn{escapechar} in a group; this also localizes the assignment
+%   performed by \texttt{e}-expansion.  The \cs{cs_show:c} and \cs{cs_log:c} commands
+%   convert their argument to a control sequence within a group to avoid
+%   showing \tn{relax} for undefined control sequences.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cs_show:N { \@@_show:NN \tl_show:n }
+\cs_new_protected:Npn \cs_show:c
+  { \group_begin: \exp_args:NNc \group_end: \cs_show:N }
+\cs_new_protected:Npn \cs_log:N { \@@_show:NN \tl_log:n }
+\cs_new_protected:Npn \cs_log:c
+  { \group_begin: \exp_args:NNc \group_end: \cs_log:N }
+\cs_new_protected:Npn \@@_show:NN #1#2
+  {
+    \group_begin:
+      \int_set:Nn \tex_escapechar:D { `\\ }
+      \exp_args:NNe
+    \group_end:
+    #1 { \token_to_str:N #2 = \cs_meaning:N #2 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\group_show_list:, \group_log_list:, \@@_group_show:NN}
+%   Wrapper around \tn{showgroups}.  Getting \TeX{} to write to the log
+%   without interruption the run is done by altering the interaction
+%   mode.
+%    \begin{macrocode}
+\cs_new_protected:Npn \group_show_list:
+  { \@@_group_show:NN \use_none:n 1 }
+\cs_new_protected:Npn \group_log_list:
+  { \@@_group_show:NN \int_gzero:N 0 }
+\cs_new_protected:Npn \@@_group_show:NN #1#2
+  {
+    \use:e
+      {
+        #1 \tex_interactionmode:D
+        \int_set:Nn \tex_tracingonline:D  {#2}
+        \int_set:Nn \tex_errorcontextlines:D { -1 }
+        \exp_not:N \exp_after:wN \scan_stop:
+        \tex_showgroups:D
+        \int_gset:Nn \tex_interactionmode:D
+          { \int_use:N \tex_interactionmode:D }
+        \int_set:Nn \tex_tracingonline:D
+          { \int_use:N \tex_tracingonline:D }
+        \int_set:Nn \tex_errorcontextlines:D
+          { \int_use:N \tex_errorcontextlines:D }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Decomposing a macro definition}
+%
+% \begin{macro}{\cs_prefix_spec:N}
+% \begin{macro}{\cs_parameter_spec:N}
+% \begin{macro}{\cs_replacement_spec:N}
+% \begin{macro}{\@@_prefix_arg_replacement:wN}
+%   We sometimes want to test if a control sequence can be expanded to
+%   reveal a hidden value. However, we cannot just expand the macro
+%   blindly as it may have arguments and none might be
+%   present. Therefore we define these functions to pick either the
+%   prefix(es), the parameter specification, or the replacement text from
+%   a macro. All of this information is returned as characters with
+%   catcode~$12$. If the token in question isn't a macro, the token
+%   \cs{scan_stop:} is returned instead.
+%    \begin{macrocode}
+\use:e
+  {
+    \exp_not:n { \cs_new:Npn \@@_prefix_arg_replacement:wN #1 }
+    \tl_to_str:n { macro : } \exp_not:n { #2 -> #3 \s_@@_stop #4 }
+  }
+  { #4 {#1} {#2} {#3} }
+\cs_new:Npn \cs_prefix_spec:N #1
+  {
+    \token_if_macro:NTF #1
+      {
+        \exp_after:wN \@@_prefix_arg_replacement:wN
+          \token_to_meaning:N #1 \s_@@_stop \use_i:nnn
+      }
+      { \scan_stop: }
+  }
+\cs_new:Npn \cs_parameter_spec:N #1
+  {
+    \token_if_macro:NTF #1
+      {
+        \exp_after:wN \@@_prefix_arg_replacement:wN
+          \token_to_meaning:N #1 \s_@@_stop \use_ii:nnn
+      }
+      { \scan_stop: }
+  }
+\cs_new:Npn \cs_replacement_spec:N #1
+  {
+    \token_if_macro:NTF #1
+      {
+        \exp_after:wN \@@_prefix_arg_replacement:wN
+          \token_to_meaning:N #1 \s_@@_stop \use_iii:nnn
+      }
+      { \scan_stop: }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Doing nothing functions}
+%
+% \begin{macro}[EXP]{\prg_do_nothing:}
+%   This does not fit anywhere else!
+%    \begin{macrocode}
+\cs_new:Npn \prg_do_nothing: { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Breaking out of mapping functions}
+%
+%    \begin{macrocode}
+%<@@=prg>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP]{\prg_break_point:Nn, \prg_map_break:Nn}
+%   In inline mappings, the nesting level must be reset
+%   at the end of the mapping, even when the user decides
+%   to break out. This is done by putting the code that
+%   must be performed as an argument of \cs{@@_break_point:Nn}.
+%   The breaking functions are then defined to jump to
+%   that point and perform the argument of \cs{@@_break_point:Nn},
+%   before the user's code (if any).  There is a check that we close the
+%   correct loop, otherwise we continue breaking.
+%    \begin{macrocode}
+\cs_new_eq:NN \prg_break_point:Nn \use_ii:nn
+\cs_new:Npn \prg_map_break:Nn #1#2#3 \prg_break_point:Nn #4#5
+  {
+    #5
+    \if_meaning:w #1 #4
+      \exp_after:wN \use_iii:nnn
+    \fi:
+    \prg_map_break:Nn #1 {#2}
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\prg_break_point:}
+% \begin{macro}{\prg_break:, \prg_break:n}
+%   Very simple analogues of \cs{prg_break_point:Nn} and
+%   \cs{prg_map_break:Nn}, for use in fast short-term recursions which
+%   are not mappings, do not need to support nesting, and in which
+%   nothing has to be done at the end of the loop.
+%    \begin{macrocode}
+\cs_new_eq:NN \prg_break_point: \prg_do_nothing:
+\cs_new:Npn \prg_break: #1 \prg_break_point: { }
+\cs_new:Npn \prg_break:n #1#2 \prg_break_point: {#1}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Starting a paragraph}
+%
+% \begin{macro}{\mode_leave_vertical:}
+%   The approach here is different to that used by \LaTeXe{} or plain \TeX{},
+%   which unbox a void box to force horizontal mode. That inserts the
+%   \tn{everypar} tokens \emph{before} the re-inserted unboxing tokens. The
+%   approach here uses a protected macro, equivalent to the \tn{quitvmode}
+%   primitive. In vertical mode, the \tn{indent} primitive is inserted:
+%   this will switch to horizontal mode and insert \tn{everypar} tokens and
+%   nothing else. Unlike the \LaTeXe{} version, the availability of \eTeX{}
+%   means using a mode test can be done at for example the start of an
+%   \tn{halign}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \mode_leave_vertical:
+  {
+    \if_mode_vertical:
+      \exp_after:wN \tex_indent:D
+    \fi:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3basics.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bitset.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bitset.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bitset.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,629 @@
+% \iffalse meta-comment
+%
+%% File: l3bitset.dtx
+%
+% Copyright (C) 2020-2024 The LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version.  The latest version
+% of this license is in the file
+%
+%    http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+%    https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full,kernel]{l3doc}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+% \title{^^A
+%   The \pkg{l3bitset} module\\ Bitsets^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% This module defines and implements the data type \texttt{bitset}, a vector of
+% bits. The size of the vector may grow dynamically.
+% Individual bits can be set and unset by names pointing to an index position.
+% The names |1|, |2|, |3|, \ldots\ are predeclared and point to the
+% index positions  $1$, $2$, $3$,\ldots. More names can be added and existing names can
+% be changed.
+% The index is like all other indices in \pkg{expl3} modules \emph{1-based}.
+% A \texttt{bitset} can be output as binary number or---as needed e.g. in a
+% PDF dictionary---as decimal (arabic) number.
+% Currently only a small subset of the functions provided by the \pkg{bitset}
+% package are implemented here, mainly the functions needed to use bitsets in
+% PDF dictionaries.
+%
+% The bitset is stored as a string (but one shouldn't rely on the internal
+% representation) and so the vector size is theoretically
+% unlimited, only restricted by \TeX-memory. But the functions to set and clear
+% bits use integer functions for the index so bitsets can't be longer
+% than $2^{31} - 1$.
+% The export function
+% \cs{bitset_to_arabic:N} can use functions from the \texttt{int} module only if
+% the largest index used for this bitset is smaller than $32$, for longer
+% bitsets \texttt{fp} is used and this is slower.
+%
+% \section{Creating bitsets}
+%
+% \begin{function}[added = 2023-11-15]
+%   {\bitset_new:N,\bitset_new:c,\bitset_new:Nn, \bitset_new:cn}
+%   \begin{syntax}
+%     \cs{bitset_new:N}  \meta{bitset var} \\
+%     \cs{bitset_new:Nn} \meta{bitset var}
+%     ~~\{
+%     ~~~~\meta{name_1} |=| \meta{index_1} |,|
+%     ~~~~\meta{name_2} |=| \meta{index_2} |,| \ldots{}
+%     ~~\}
+%   \end{syntax}
+% Creates a new \meta{bitset var} or raises an error if the name is already taken.
+% The declaration is global. The \meta{bitset var} is initially $0$.
+%
+% Bitsets are implemented as string variables consisting of
+% \texttt{1}'s and \texttt{0}'s.
+% The rightmost number is the index position $1$, so
+% the string variable can be viewed directly as the binary number.
+% But one shouldn't rely on the internal representation, but use the
+% dedicated \cs{bitset_to_bin:N} instead to get the binary number.
+%
+% The name--index pairs given in the second
+% argument of \cs{bitset_new:Nn} declares names for some indices,
+% which can be used to set and unset bits.
+% The names |1|, |2|, |3|, \ldots\ are predeclared and point to the
+% index positions $1$, $2$, $3$, \ldots.
+%
+% \meta{index\ldots} should be a positive number or an
+% \meta{integer expression} which evaluates to a positive number.
+% The expression is evaluated when the index is used, not at declaration time.
+% The names \meta{name\ldots}
+% should be unique. Using a number as name, e.g.~|10=1|, is allowed, it
+% then overwrites the predeclared name |10|,
+% but the index position $10$ can then only be reached if some other
+% name for it exists, e.g. |ten=10|.
+% It is not necessary to give every index
+% a name, and an index can have more than one name. The named index
+% can be extended or changed with the next function.
+% \end{function}
+%
+% \begin{function}[added = 2023-11-15]
+%   {\bitset_addto_named_index:Nn}
+%   \begin{syntax}
+%     \cs{bitset_addto_named_index:Nn} \meta{bitset var}
+%     ~~\{
+%     ~~~~\meta{name_1} |=| \meta{index_1} |,|
+%     ~~~~\meta{name_2} |=| \meta{index_2} |,| \ldots{}
+%     ~~\}
+%   \end{syntax}
+%   This extends or changes the name--index pairs for \meta{bitset var}
+%   globally as described for \cs{bitset_new:Nn}.
+% \end{function}
+%
+% For example after these settings
+% \begin{verbatim}
+%   \bitset_new:Nn \l_pdfannot_F_bitset
+%     {
+%       Invisible      = 1,
+%       Hidden         = 2,
+%       Print          = 3,
+%       NoZoom         = 4,
+%       NoRotate       = 5,
+%       NoView         = 6,
+%       ReadOnly       = 7,
+%       Locked         = 8,
+%       ToggleNoView   = 9,
+%       LockedContents = 10
+%     }
+%   \bitset_addto_named_index:Nn \l_pdfannot_F_bitset
+%     {
+%       print = 3
+%     }
+% \end{verbatim}
+% it is possible to set bit $3$ by using any of these alternatives:
+% \begin{verbatim}
+%   \bitset_set_true:Nn \l_pdfannot_F_bitset {Print}
+%   \bitset_set_true:Nn \l_pdfannot_F_bitset {print}
+%   \bitset_set_true:Nn \l_pdfannot_F_bitset {3}
+% \end{verbatim}
+%
+% \begin{function}[EXP, pTF,added = 2023-11-15]
+%   {\bitset_if_exist:N, \bitset_if_exist:c}
+%   \begin{syntax}
+%     \cs{bitset_if_exist_p:N} \meta{bitset var}
+%     \cs{bitset_if_exist:NTF} \meta{bitset var} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{bitset var} exist.
+% \end{function}
+%
+% \section{Setting and unsetting bits}
+%
+% \begin{function}[added = 2023-11-15]
+%   {
+%     \bitset_set_true:Nn, \bitset_set_true:cn,
+%     \bitset_gset_true:Nn, \bitset_gset_true:cn
+%   }
+%   \begin{syntax}
+%     \cs{bitset_set_true:Nn} \meta{bitset var} \Arg{name}
+%   \end{syntax}
+%   This sets the bit of the index position represented by \Arg{name} to $1$.
+%   \meta{name} should be either one of the predeclared names
+%   |1|, |2|, |3|, \ldots, or one of the names added manually.
+%   Index position are 1-based.
+%   If needed the length of the bit vector is enlarged.
+% \end{function}
+%
+% \begin{function}[added = 2023-11-15]
+%   {
+%     \bitset_set_false:Nn, \bitset_set_false:cn,
+%     \bitset_gset_false:Nn, \bitset_gset_false:cn
+%   }
+%   \begin{syntax}
+%     \cs{bitset_set_false:Nn} \meta{bitset var} \Arg{name}
+%   \end{syntax}
+%   This unsets the bit of the index position represented by \Arg{name} (sets
+%   it to $0$).
+%   \meta{name} should be either one of the predeclared names
+%   |1|, |2|, |3|, \ldots, or one of the names added manually.
+%   The index is $1$-based. If the index position is larger
+%   than the current length of the bit vector
+%   nothing happens. If the leading (left most) bit is unset,
+%   zeros are not trimmed but stay in the bit vector and are still shown
+%   by \cs{bitset_show:N}.
+% \end{function}
+%
+% \begin{function}[added = 2023-11-15]
+%   {\bitset_clear:N,\bitset_clear:c,\bitset_gclear:N,\bitset_gclear:c}
+%   \begin{syntax}
+%     \cs{bitset_clear:N} \meta{bitset var}
+%   \end{syntax}
+%   This resets the bitset to the initial state. The declared names are not changed.
+% \end{function}
+%
+% \section{Using bitsets}
+%
+% \begin{function}[EXP,added = 2023-11-15]
+%   {\bitset_item:Nn, \bitset_item:cn}
+%   \begin{syntax}
+%     \cs{bitset_item:Nn} \meta{bitset var} \Arg{name}
+%   \end{syntax}
+% \cs{bitset_item:Nn} outputs \texttt{1} if the bit with
+% the index number represented by \meta{name} is set and \texttt{0} otherwise.
+%  \meta{name} is either one of the predeclared names
+% |1|, |2|, |3|, \ldots, or one of the names added manually.
+% \end{function}
+%
+% \begin{function}[EXP,added = 2023-11-15]
+%   {\bitset_to_bin:N, \bitset_to_bin:c}
+%   \begin{syntax}
+%     \cs{bitset_to_bin:N} \meta{bitset var}
+%   \end{syntax}
+%   This leaves the current value of the bitset expressed as
+%   a binary (string) number in the input stream.
+%   If no bit has been set yet, the output is zero.
+% \end{function}
+%
+% \begin{function}[EXP,added = 2023-11-15]
+%   {\bitset_to_arabic:N, \bitset_to_arabic:c}
+%   \begin{syntax}
+%     \cs{bitset_to_arabic:N} \meta{bitset var}
+%   \end{syntax}
+%   This leaves the current value of the bitset expressed as
+%   a decimal number in the input stream. If no bit has been set yet,
+%   the output is zero. The function uses \cs{int_from_bin:n} if the largest
+%   index that have been set or unset is smaller than $32$, and a slower
+%   implementation based on \cs{fp_eval:n} otherwise.
+% \end{function}
+%
+% \begin{function}[added = 2023-11-15]
+%   {\bitset_show:N, \bitset_show:c}
+%   \begin{syntax}
+%     \cs{bitset_show:N} \meta{bitset var}
+%   \end{syntax}
+%   Displays the binary and decimal values of the \meta{bitset var}
+%   on the terminal.
+% \end{function}
+%
+% \begin{function}[added = 2023-11-15]
+%   {\bitset_log:N, \bitset_log:c}
+%   \begin{syntax}
+%     \cs{bitset_log:N} \meta{bitset var}
+%   \end{syntax}
+%   Writes the binary and decimal values of the \meta{bitset var}
+%   in the log file.
+% \end{function}
+%
+% \begin{function}[added = 2023-11-15]
+%  {
+%     \bitset_show_named_index:N, \bitset_show_named_index:c
+%  }
+%   \begin{syntax}
+%     \cs{bitset_show_named_index:N} \meta{bitset var}
+%   \end{syntax}
+%   Displays declared name--index pairs of the \meta{bitset var}
+%   on the terminal.
+% \end{function}
+%
+% \begin{function}[added = 2023-12-11]
+%  {
+%     \bitset_log_named_index:N, \bitset_log_named_index:c
+%  }
+%   \begin{syntax}
+%     \cs{bitset_log_named_index:N} \meta{bitset var}
+%   \end{syntax}
+%   Writes declared name--index pairs of the \meta{bitset var}
+%   in the log file.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3bitset} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=bitset>
+%    \end{macrocode}
+%
+% Transitional support.
+%    \begin{macrocode}
+\cs_if_exist:NT \@expl at finalise@setup@@@@
+  {
+    \tl_gput_right:Nn \@expl at finalise@setup@@@@
+      { \declare at file@substitution { l3bitset.sty } { null.tex } }
+  }
+%    \end{macrocode}
+%
+% A bitset is a string variable.
+%  \begin{macro}{\bitset_new:N, \bitset_new:c}
+%  \begin{macro}{\bitset_new:Nn, \bitset_new:cn}
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_new:N #1
+  {
+    \__kernel_chk_if_free_cs:N #1
+    \cs_gset_eq:NN #1 \c_zero_str
+    \prop_new:c { g__bitset_ \cs_to_str:N #1 _name_prop }
+  }
+\cs_new_protected:Npn \bitset_new:Nn #1 #2
+  {
+    \__kernel_chk_if_free_cs:N #1
+    \cs_gset_eq:NN #1 \c_zero_str
+    \prop_new:c { g__bitset_ \cs_to_str:N #1 _name_prop }
+    \prop_gset_from_keyval:cn
+      { g__bitset_ \cs_to_str:N #1 _name_prop }
+      {#2}
+  }
+\cs_generate_variant:Nn \bitset_new:N { c }
+\cs_generate_variant:Nn \bitset_new:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\bitset_addto_named_index:Nn}
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_addto_named_index:Nn #1#2
+  {
+    \prop_gput_from_keyval:cn
+      { g_@@_ \cs_to_str:N #1 _name_prop } { #2 }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[EXP,pTF]
+%   {
+%     \bitset_if_exist:N, \bitset_if_exist:c
+%   }
+% Existence tests.
+%    \begin{macrocode}
+\prg_new_eq_conditional:NNn
+  \bitset_if_exist:N \str_if_exist:N { p , T , F , TF }
+\prg_new_eq_conditional:NNn
+  \bitset_if_exist:c \str_if_exist:c { p , T , F , TF }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_set_true:Nn, \@@_gset_true:Nn, \@@_set_false:Nn, \@@_gset_false:Nn}
+% \begin{macro}{\@@_set:NNnN}
+% The internal command uses only numbers (integer expressions) for the
+% position.
+% A bit is set by either extending the string or by splitting it and
+% then inserting an $1$. It is not checked if the value was already $1$.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_set_true:Nn #1#2
+  { \@@_set:NNnN \str_set:Ne #1 {#2} 1 }
+\cs_new_protected:Npn \@@_gset_true:Nn #1#2
+  { \@@_set:NNnN \str_gset:Ne #1 {#2} 1 }
+\cs_new_protected:Npn \@@_set_false:Nn #1#2
+  { \@@_set:NNnN \str_set:Ne #1 {#2} 0 }
+\cs_new_protected:Npn \@@_gset_false:Nn #1#2
+  { \@@_set:NNnN \str_gset:Ne #1 {#2} 0 }
+\cs_new_protected:Npn \@@_set:NNnN #1#2#3#4
+  {
+    \int_compare:nNnT {#3} > { 0 }
+      {
+        \int_compare:nNnTF { \str_count:N #2 } < {#3}
+          {
+            #1 #2
+              {
+                #4
+                \prg_replicate:nn { #3 - \str_count:N #2 - 1 } { 0 }
+                #2
+              }
+          }
+          {
+            #1 #2
+              {
+                \str_range:Nnn #2 { 1 } { -1 - (#3) }
+                #4
+                \str_range:Nnn #2 { 1 - (#3) } { -1 }
+              }
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_internal_int}
+%    \begin{macrocode}
+\int_new:N \l_@@_internal_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[TF]{\@@_test_digits:n}
+% \begin{macro}{\@@_test_digits_end:n}
+% \begin{macro}{\@@_test_digits:w}
+%   \url{https://chat.stackexchange.com/transcript/message/56878159#56878159}
+%    \begin{macrocode}
+\prg_new_protected_conditional:Npnn \@@_test_digits:n #1 { TF }
+  {
+    \tex_afterassignment:D \@@_test_digits:w
+    \l_@@_internal_int = 0 \tl_trim_spaces_apply:nN {#1} \tl_to_str:n
+    \@@_test_digits_end:
+    \use_i:nnn \if_false:
+    \@@_test_digits_end:
+    \if_int_compare:w \c_zero_int < \l_@@_internal_int
+      \prg_return_true:
+    \else:
+      \prg_return_false:
+    \fi:
+  }
+\cs_new_eq:NN \@@_test_digits_end: \exp_stop_f:
+\cs_new_protected:Npn \@@_test_digits:w #1 \@@_test_digits_end: { }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \bitset_set_true:Nn, \bitset_set_true:cn,
+%     \bitset_gset_true:Nn, \bitset_gset_true:cn,
+%     \bitset_set_false:Nn, \bitset_set_false:cn,
+%     \bitset_gset_false:Nn, \bitset_gset_false:cn
+%   }
+% \begin{macro}{\@@_set_aux:NNn}
+% The user commands must first translate the argument to an index number.
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_set_true:Nn #1#2
+  { \@@_set:NNn \@@_set_true:Nn #1 {#2} }
+\cs_new_protected:Npn \bitset_gset_true:Nn #1#2
+  { \@@_set:NNn \@@_gset_true:Nn #1 {#2} }
+\cs_new_protected:Npn \bitset_set_false:Nn #1#2
+  { \@@_set:NNn \@@_set_false:Nn #1 {#2} }
+\cs_new_protected:Npn \bitset_gset_false:Nn #1#2
+  { \@@_set:NNn \@@_gset_false:Nn #1 {#2} }
+\cs_new_protected:Npn \@@_set:NNn #1#2#3
+  {
+    \prop_if_in:cnTF { g_@@_ \cs_to_str:N #2 _name_prop } {#3}
+      {
+        #1 #2
+          {
+            \prop_item:cn  { g_@@_ \cs_to_str:N #2 _name_prop } {#3}
+          }
+      }
+      {
+        \@@_test_digits:nTF {#3}
+          {
+            #1 #2 {#3}
+            \prop_gput:cnn { g_@@_ \cs_to_str:N #2 _name_prop } {#3} {#3}
+          }
+          {
+            \msg_warning:nnee { bitset } { unknown-name }
+              { \token_to_str:N #2 }
+              { \tl_to_str:n {#3} }
+          }
+      }
+  }
+\cs_generate_variant:Nn \bitset_set_true:Nn  { c }
+\cs_generate_variant:Nn \bitset_gset_true:Nn { c }
+\cs_generate_variant:Nn \bitset_set_false:Nn  { c }
+\cs_generate_variant:Nn \bitset_gset_false:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \bitset_clear:N,  \bitset_clear:c,
+%     \bitset_gclear:N, \bitset_gclear:c
+%   }
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_clear:N #1
+  {
+    \str_set_eq:NN #1 \c_zero_str
+  }
+\cs_new_protected:Npn \bitset_gclear:N #1
+  {
+    \str_gset_eq:NN #1 \c_zero_str
+  }
+\cs_generate_variant:Nn \bitset_clear:N { c }
+\cs_generate_variant:Nn \bitset_gclear:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {
+%     \bitset_to_arabic:N, \bitset_to_arabic:c,
+%     \bitset_to_bin:N,    \bitset_to_bin:c,
+%   }
+% \begin{macro}[EXP]{\@@_to_int:nN}
+%   The naming of the commands follow the names in the \texttt{int} module.
+%   \cs{bitset_to_arabic:N} uses \cs{int_from_bin:n} if the string is shorter
+%   than $32$ and the slower \cs{fp_eval:n} for larger bitsets.
+%    \begin{macrocode}
+\cs_new:Npn \bitset_to_arabic:N #1
+  {
+    \int_compare:nNnTF { \str_count:N #1 } < { 32 }
+      { \exp_args:No \int_from_bin:n {#1} }
+      {
+        \exp_after:wN \@@_to_int:nN \exp_after:wN 0
+        #1 \q_recursion_tail \q_recursion_stop
+      }
+  }
+\cs_new:Npn \@@_to_int:nN #1#2
+  {
+    \quark_if_recursion_tail_stop_do:Nn #2 {#1}
+    \exp_args:Nf \@@_to_int:nN { \fp_eval:n { #1 * 2 + #2 } }
+  }
+\cs_new:Npn \bitset_to_bin:N #1
+  {
+    #1
+  }
+\cs_generate_variant:Nn \bitset_to_arabic:N  { c }
+\cs_generate_variant:Nn \bitset_to_bin:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \bitset_item:Nn, \bitset_item:cn
+%   }
+% All bits that have been set at anytime have an entry in the prop,
+% so we can take everything else as $0$.
+%    \begin{macrocode}
+\cs_new:Npn \bitset_item:Nn #1#2
+  {
+    \prop_if_in:cnTF { g_@@_ \cs_to_str:N #1 _name_prop } {#2}
+      {
+        \int_eval:n
+          {
+            \str_item:Nn #1
+              { 0 - ( \prop_item:cn { g_@@_ \cs_to_str:N #1 _name_prop } {#2} ) }
+            +0
+          }
+      }
+      {
+        0
+      }
+  }
+\cs_generate_variant:Nn \bitset_item:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \bitset_show:N, \bitset_show:c,
+%     \bitset_log:N,  \bitset_log:c
+%   }
+%    \begin{macrocode}
+\cs_new_protected:Npn   \bitset_show:N { \@@_show:NN \msg_show:nneeee }
+\cs_generate_variant:Nn \bitset_show:N { c }
+\cs_new_protected:Npn   \bitset_log:N  { \@@_show:NN \msg_log:nneeee }
+\cs_generate_variant:Nn \bitset_log:N  { c }
+\cs_new_protected:Npn \@@_show:NN #1#2
+  {
+    \__kernel_chk_defined:NT #2
+      {
+        #1 { bitset } { show }
+          { \token_to_str:N #2 }
+          { \bitset_to_bin:N #2 }
+          { \bitset_to_arabic:N #2 }
+          { }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%  {
+%     \bitset_show_named_index:N, \bitset_show_named_index:c,
+%     \bitset_log_named_index:N,  \bitset_log_named_index:c
+%  }
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_show_named_index:N
+  { \@@_show_named_index:NN \msg_show:nneeee }
+\cs_generate_variant:Nn \bitset_show_named_index:N { c }
+\cs_new_protected:Npn \bitset_log_named_index:N
+  { \@@_show_named_index:NN \msg_log:nneeee }
+\cs_generate_variant:Nn \bitset_log_named_index:N { c }
+\cs_new_protected:Npn \@@_show_named_index:NN #1#2
+  {
+    \__kernel_chk_defined:NT #2
+      {
+        #1 { bitset } { show-names }
+          { \token_to_str:N #2 }
+          { \prop_map_function:cN { g_@@_ \cs_to_str:N #2 _name_prop } \msg_show_item:nn }
+          { } { }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Messages}
+%    \begin{macrocode}
+\msg_new:nnn { bitset } { show }
+  {
+    The~bitset~#1~has~the~representation: \\
+    >~binary:~#2  \\
+    >~arabic:~#3 .
+  }
+\msg_new:nnn { bitset } { show-names }
+  {
+    The~bitset~#1~
+    \tl_if_empty:nTF {#2}
+      { knows~no~names~yet \\>~ . }
+      { knows~the~name/index~pairs~(without~outer~braces): #2 . }
+  }
+\msg_new:nnn { bitset } { unknown-name }
+  { The~name~'#2'~is~unknown~for~bitset~\tl_to_str:n {#1} }
+\prop_gput:Nnn \g_msg_module_name_prop { bitset } { LaTeX }
+\prop_gput:Nnn \g_msg_module_type_prop { bitset } { }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bitset.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bootstrap.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bootstrap.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bootstrap.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,357 @@
+% \iffalse meta-comment
+%
+%% File: l3bootstrap.dtx
+%
+% Copyright (C) 2011-2024 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 \pkg{l3bootstrap} module\\ Bootstrap code^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \section{Using the \LaTeX3 modules}
+%
+% The modules documented in ^^A
+% \ifinterface
+%   this file (and \file{source3} for documented sources) ^^A
+% \else
+%   \file{interface3} (and this file) ^^A
+% \fi
+% are designed to be used on top of \LaTeXe{} and are already pre-loaded
+% since \LaTeXe{} 2020-02-02.
+% To support older formats, the |\usepackage{expl3}| or |\RequirePackage{expl3}|
+% instructions are still available to load them all as one.
+%
+% As the modules use a coding syntax different from standard
+% \LaTeXe{} it provides a few functions for setting it up.
+%
+% \begin{function}[updated = 2011-08-13]{\ExplSyntaxOn, \ExplSyntaxOff}
+%   \begin{syntax}
+%     \cs{ExplSyntaxOn} \meta{code} \cs{ExplSyntaxOff}
+%   \end{syntax}
+%   The \cs{ExplSyntaxOn} function switches to a category code
+%   regime in which spaces and new lines are ignored, and in which the colon (|:|)
+%   and underscore (|_|) are treated as \enquote{letters}, thus allowing
+%   access to the names of code functions and variables. Within this
+%   environment, |~| is used to input a space. The \cs{ExplSyntaxOff}
+%   reverts to the document category code regime.
+%   \begin{texnote}
+%     Spaces introduced by~|~| behave much in the same way as normal
+%     space characters in the standard category code regime: they are
+%     ignored after a control word or at the start of a line, and
+%     multiple consecutive~|~| are equivalent to a single one.  However,
+%     |~|~is \emph{not} ignored at the end of a line.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[updated = 2017-03-19, updated = 2023-08-03]
+%   {\ProvidesExplPackage, \ProvidesExplClass, \ProvidesExplFile}
+%   \begin{syntax}
+%     \cs{ProvidesExplPackage} \Arg{package} \Arg{date} \Arg{version} \Arg{description}
+%   \end{syntax}
+%   These functions act broadly in the same way as the corresponding
+%   \LaTeXe{} kernel
+%   functions \tn{ProvidesPackage}, \tn{ProvidesClass} and
+%   \tn{ProvidesFile}. However, they also implicitly switch
+%   \cs{ExplSyntaxOn} for the remainder of the code with the file. At the
+%   end of the file, \cs{ExplSyntaxOff} will be called to reverse this.
+%   (This is the same concept as \LaTeXe{} provides in turning on
+%   \tn{makeatletter} within package and class code.) The \meta{date} should
+%   be given in the format \meta{year}/\meta{month}/\meta{day} or in the ISO
+%   date format \meta{year}-\meta{month}-\meta{day}. If the
+%   \meta{version} is given then a leading \texttt{v} is optional: if given
+%   as a \enquote{pure} version string, a \texttt{v} will be prepended.
+% \end{function}
+%
+% \begin{function}[updated = 2012-06-04]{\GetIdInfo}
+%   \begin{syntax}
+%     \cs{GetIdInfo} |$Id:| \meta{SVN info field} |$| \Arg{description}
+%   \end{syntax}
+%   Extracts all information from a SVN field. Spaces are not
+%   ignored in these fields. The information pieces are stored in
+%   separate control sequences with \cs{ExplFileName} for the part of the
+%   file name leading up to the period, \cs{ExplFileDate} for date,
+%   \cs{ExplFileVersion} for version and \cs{ExplFileDescription} for the
+%   description.
+% \end{function}
+%
+% To summarize: Every single package using this syntax should identify
+% itself using one of the above methods. Special care is taken so that
+% every package or class file loaded with \tn{RequirePackage} or similar
+% are loaded with usual \LaTeXe{} category codes and the \LaTeX3 category code
+% scheme is reloaded when needed afterwards. See implementation for
+% details. If you use the \cs{GetIdInfo} command you can use the
+% information when loading a package with
+% \begin{verbatim}
+%   \ProvidesExplPackage{\ExplFileName}
+%     {\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+% \end{verbatim}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3bootstrap} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%<@@=kernel>
+%    \end{macrocode}
+%
+% \subsection{The \tn{pdfstrcmp} primitive in \XeTeX{}}
+%
+% Only \pdfTeX{} has a primitive called \tn{pdfstrcmp}. The \XeTeX{}
+% version is just \tn{strcmp}, so there is some shuffling to do. As
+% this is still a real primitive, using the \pdfTeX{} name is \enquote{safe}.
+%    \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+  \expandafter\ifx\csname pdfstrcmp\endcsname\relax
+  \let\pdfstrcmp\strcmp
+\fi
+%    \end{macrocode}
+%
+% \subsection{Loading support \Lua{} code}
+%
+% When \LuaTeX{} is used there are various pieces of \Lua{} code which need to
+% be loaded. The code itself is defined in \pkg{l3luatex} and is extracted into
+% a separate file. Thus here the task is to load the \Lua{} code both now and
+% (if required) at the start of each job.
+%    \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname directlua\endcsname\relax
+\else
+  \ifnum\luatexversion<110 %
+  \else
+%    \end{macrocode}
+%   For \LuaTeX{} we make sure the basic support is loaded:
+%   this is only necessary in plain.
+%    \begin{macrocode}
+    \begingroup\expandafter\expandafter\expandafter\endgroup
+    \expandafter\ifx\csname newcatcodetable\endcsname\relax
+      \input{ltluatex}%
+    \fi
+    \begingroup\expandafter\expandafter\expandafter\endgroup
+    \expandafter\ifx\csname newluabytecode\endcsname\relax
+    \else
+      \newluabytecode\@expl at luadata@bytecode
+    \fi
+    \directlua{require("expl3")}%
+%    \end{macrocode}
+%   As the user might be making a custom format, no assumption is made about
+%   matching package mode with only loading the \Lua{} code once. Instead, a
+%   query to \Lua{} reveals what mode is in operation.
+%    \begin{macrocode}
+    \ifnum 0%
+      \directlua{
+        if status.ini_version then
+          tex.write("1")
+        end
+      }>0 %
+      \everyjob\expandafter{%
+        \the\expandafter\everyjob
+        \csname\detokenize{lua_now:n}\endcsname{require("expl3")}%
+      }%
+    \fi
+  \fi
+\fi
+%    \end{macrocode}
+%
+% \subsection{Engine requirements}
+%
+% The code currently requires \eTeX{}, the set of \enquote{\pdfTeX{}
+% extensions} \emph{including} \tn{expanded}, and for Unicode engines the
+% ability to generate arbitrary character tokens by expansion. That is covered
+% by all supported engines since \TeX{} Live 2019, which we therefore use
+% as a baseline for engine and \LaTeX{} format support.
+% For \LuaTeX, we require at least Lua 5.3 and the |token.set_lua| function.
+% This is available at least since \LuaTeX{} 1.10, which again is the one
+% in \TeX{} Live 2019. (u)p\TeX{} only gained \tn{ifincsname} for \TeX{}
+% Live 2020, but at present that primitive is unused in \pkg{expl3} so for
+% the present it's not tested. If and when that changes, we will need to
+% revisit the code here.
+%    \begin{macrocode}
+\begingroup
+  \def\next{\endgroup}%
+  \def\ShortText{Required primitives not found}%
+  \def\LongText%
+    {%
+      The L3 programming layer requires the e-TeX primitives and the
+      \LineBreak 'pdfTeX utilities' as described in the README file.
+      \LineBreak
+      These are available in the engines\LineBreak
+      - pdfTeX v1.40.20\LineBreak
+      - XeTeX v0.999991\LineBreak
+      - LuaTeX v1.10\LineBreak
+      - e-(u)pTeX v3.8.2\LineBreak
+      - Prote (2021)\LineBreak
+      or later.\LineBreak
+      \LineBreak
+    }%
+  \ifnum0%
+    \expandafter\ifx\csname luatexversion\endcsname\relax
+      \expandafter\ifx\csname expanded\endcsname\relax\else 1\fi
+    \else
+      \ifnum\luatexversion<110 \else 1\fi
+    \fi
+    =0 %
+      \newlinechar`\^^J %
+      \def\LineBreak{\noexpand\MessageBreak}%
+      \expandafter\ifx\csname PackageError\endcsname\relax
+        \def\LineBreak{^^J}%
+        \begingroup
+          \lccode`\~=`\ \lccode`\}=`\ %
+          \lccode`\T=`\T\lccode`\H=`\H%
+          \catcode`\ =11 %
+\lowercase{\endgroup\def\PackageError#1#2#3{%
+\begingroup\errorcontextlines-1\immediate\write0{}\errhelp{#3}\def%
+\                                                   {#1 Error: #2.^^J^^J
+Type  H <return>  for immediate help}\def~{\errmessage{%
+\                                                   }}~\endgroup}}%
+      \fi
+      \edef\next
+        {%
+          \noexpand\PackageError{expl3}{\ShortText}
+            {\LongText Loading of expl3 will abort!}%
+          \endgroup
+          \noexpand\endinput
+        }%
+  \fi
+\next
+%    \end{macrocode}
+%
+% \subsection{The \LaTeX3 code environment}
+%
+% The code environment is now set up.
+%
+% \begin{macro}{\ExplSyntaxOff}
+%   Before changing any category codes, in package mode we need to save
+%   the situation before loading. Note the set up here means that once applied
+%   \cs{ExplSyntaxOff} becomes a \enquote{do nothing} command until
+%   \cs{ExplSyntaxOn} is used.
+%    \begin{macrocode}
+\protected\edef\ExplSyntaxOff
+  {%
+    \protected\def\noexpand\ExplSyntaxOff{}%
+    \catcode   9 = \the\catcode   9\relax
+    \catcode  32 = \the\catcode  32\relax
+    \catcode  34 = \the\catcode  34\relax
+    \catcode  58 = \the\catcode  58\relax
+    \catcode  94 = \the\catcode  94\relax
+    \catcode  95 = \the\catcode  95\relax
+    \catcode 124 = \the\catcode 124\relax
+    \catcode 126 = \the\catcode 126\relax
+    \endlinechar = \the\endlinechar\relax
+    \chardef\csname\detokenize{l_@@_expl_bool}\endcsname = 0\relax
+  }%
+%    \end{macrocode}
+% \end{macro}
+%
+% The code environment is now set up.
+%    \begin{macrocode}
+\catcode 9   = 9\relax
+\catcode 32  = 9\relax
+\catcode 34  = 12\relax
+\catcode 58  = 11\relax
+\catcode 94  = 7\relax
+\catcode 95  = 11\relax
+\catcode 124 = 12\relax
+\catcode 126 = 10\relax
+\endlinechar = 32\relax
+%    \end{macrocode}
+%
+% \begin{variable}{\l_@@_expl_bool}
+%   The status for code syntax: this is on at present.
+%    \begin{macrocode}
+\global\chardef\l_@@_expl_bool = 1\relax
+%    \end{macrocode}
+%\end{variable}
+%
+% \begin{macro}{\ExplSyntaxOn}
+%  The idea here is that multiple \cs{ExplSyntaxOn} calls are not
+%  going to mess up category codes, and that multiple calls to
+%  \cs{ExplSyntaxOff} are also not wasting time. Applying
+%  \cs{ExplSyntaxOn} alters the definition of \cs{ExplSyntaxOff}
+%  and so in package mode this function should not be used until after
+%  the end of the loading process!
+%    \begin{macrocode}
+\protected \def \ExplSyntaxOn
+  {
+    \bool_if:NF \l_@@_expl_bool
+      {
+        \cs_set_protected:Npe \ExplSyntaxOff
+          {
+            \char_set_catcode:nn { 9 }   { \char_value_catcode:n { 9 } }
+            \char_set_catcode:nn { 32 }  { \char_value_catcode:n { 32 } }
+            \char_set_catcode:nn { 34 }  { \char_value_catcode:n { 34 } }
+            \char_set_catcode:nn { 58 }  { \char_value_catcode:n { 58 } }
+            \char_set_catcode:nn { 94 }  { \char_value_catcode:n { 94 } }
+            \char_set_catcode:nn { 95 }  { \char_value_catcode:n { 95 } }
+            \char_set_catcode:nn { 124 } { \char_value_catcode:n { 124 } }
+            \char_set_catcode:nn { 126 } { \char_value_catcode:n { 126 } }
+            \tex_endlinechar:D =
+              \tex_the:D \tex_endlinechar:D \scan_stop:
+            \bool_set_false:N \l_@@_expl_bool
+            \cs_set_protected:Npn \ExplSyntaxOff { }
+          }
+      }
+    \char_set_catcode_ignore:n           { 9 }   % tab
+    \char_set_catcode_ignore:n           { 32 }  % space
+    \char_set_catcode_other:n            { 34 }  % double quote
+    \char_set_catcode_letter:n           { 58 }  % colon
+    \char_set_catcode_math_superscript:n { 94 }  % circumflex
+    \char_set_catcode_letter:n           { 95 }  % underscore
+    \char_set_catcode_other:n            { 124 } % pipe
+    \char_set_catcode_space:n            { 126 } % tilde
+    \tex_endlinechar:D = 32 \scan_stop:
+    \bool_set_true:N \l_@@_expl_bool
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3bootstrap.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3box.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3box.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3box.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,2530 @@
+% \iffalse meta-comment
+%
+%% File: l3box.dtx
+%
+% Copyright (C) 2005-2024 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 \pkg{l3box} module\\ Boxes^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% Box variables contain typeset material that can be inserted on the
+% page or in other boxes.  Their contents cannot be converted back to
+% lists of tokens.
+% There are three kinds of box operations: horizontal mode denoted
+% with prefix |\hbox_|, vertical mode with prefix |\vbox_|, and the
+% generic operations working in both modes with prefix |\box_|.
+% For instance, a new box variable containing the words \enquote{Hello,
+% world!} (in a horizontal box) can be obtained by the following code.
+% \begin{verbatim}
+% \box_new:N \l_hello_box
+% \hbox_set:Nn \l_hello_box { Hello, ~ world! }
+% \end{verbatim}
+% The argument is typeset inside a \TeX{} group so that any variables
+% assigned during the construction of this box restores its value
+% afterwards.
+%
+% Box variables from \pkg{l3box} are compatible with those of \LaTeXe{}
+% and plain \TeX{} and can be used interchangeably.  The \pkg{l3box}
+% commands to construct boxes, such as \cs{hbox:n} or \cs{hbox_set:Nn},
+% are \enquote{color-safe}, meaning that
+% \begin{verbatim}
+% \hbox:n { \color_select:n { blue } Hello, } ~ world!
+% \end{verbatim}
+% will result in \enquote{Hello,} taking the color blue, but
+% \enquote{world!} remaining with the prevailing color outside the box.
+%
+% \section{Creating and initialising boxes}
+%
+% \begin{function}{\box_new:N, \box_new:c}
+%   \begin{syntax}
+%     \cs{box_new:N} \meta{box}
+%   \end{syntax}
+%   Creates a new \meta{box} or raises an error if the name is
+%   already taken. The declaration is global. The \meta{box} is
+%   initially void.
+% \end{function}
+%
+% \begin{function}{\box_clear:N, \box_clear:c, \box_gclear:N, \box_gclear:c}
+%   \begin{syntax}
+%     \cs{box_clear:N} \meta{box}
+%   \end{syntax}
+%   Clears the content of the \meta{box} by setting the box equal to
+%   \cs{c_empty_box}.
+% \end{function}
+%
+% \begin{function}
+%   {\box_clear_new:N, \box_clear_new:c, \box_gclear_new:N, \box_gclear_new:c}
+%   \begin{syntax}
+%     \cs{box_clear_new:N} \meta{box}
+%   \end{syntax}
+%   Ensures that the \meta{box} exists globally by applying
+%   \cs{box_new:N} if necessary, then applies
+%   \cs[index=box_clear:N]{box_(g)clear:N} to leave
+%   the \meta{box} empty.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \box_set_eq:NN,  \box_set_eq:cN,  \box_set_eq:Nc,  \box_set_eq:cc,
+%     \box_gset_eq:NN, \box_gset_eq:cN, \box_gset_eq:Nc, \box_gset_eq:cc
+%   }
+%   \begin{syntax}
+%     \cs{box_set_eq:NN} \meta{box_1} \meta{box_2}
+%   \end{syntax}
+%   Sets the content of \meta{box_1} equal to that of \meta{box_2}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added=2012-03-03]
+%   {\box_if_exist:N, \box_if_exist:c}
+%   \begin{syntax}
+%     \cs{box_if_exist_p:N} \meta{box}
+%     \cs{box_if_exist:NTF} \meta{box} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{box} is currently defined.  This does not
+%   check that the \meta{box} really is a box.
+% \end{function}
+%
+% \section{Using boxes}
+%
+% \begin{function}{\box_use:N, \box_use:c}
+%   \begin{syntax}
+%     \cs{box_use:N} \meta{box}
+%   \end{syntax}
+%   Inserts the current content of the \meta{box} onto the current
+%   list for typesetting. An error is raised if the variable does
+%   not exist or if it is invalid.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{copy}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}{\box_move_right:nn, \box_move_left:nn}
+%   \begin{syntax}
+%     \cs{box_move_right:nn} \Arg{dim expr} \Arg{box function}
+%   \end{syntax}
+%   This function operates in vertical mode, and inserts the
+%   material specified by the \meta{box function}
+%   such that its reference point is displaced horizontally by the given
+%   \meta{dim expr} from the reference point for typesetting, to the right
+%   or left as appropriate. The \meta{box function} should be
+%   a box operation such as \cs{box_use:N} |\<box>| or a \enquote{raw}
+%   box specification such as \cs{vbox:n} |{ xyz }|.
+% \end{function}
+%
+% \begin{function}{\box_move_up:nn, \box_move_down:nn}
+%   \begin{syntax}
+%     \cs{box_move_up:nn} \Arg{dim expr} \Arg{box function}
+%   \end{syntax}
+%   This function operates in horizontal mode, and inserts the
+%   material specified by the \meta{box function}
+%   such that its reference point is displaced vertically by the given
+%   \meta{dim expr} from the reference point for typesetting, up
+%   or down as appropriate. The \meta{box function} should be
+%   a box operation such as \cs{box_use:N} |\<box>| or a \enquote{raw}
+%   box specification such as \cs{vbox:n} |{ xyz }|.
+% \end{function}
+%
+% \section{Measuring and setting box dimensions}
+%
+% \begin{function}{\box_dp:N, \box_dp:c}
+%   \begin{syntax}
+%     \cs{box_dp:N} \meta{box}
+%   \end{syntax}
+%   Calculates the depth (below the baseline) of the \meta{box}
+%   in a form suitable for use in a \meta{dim expr}.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{dp}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}{\box_ht:N, \box_ht:c}
+%   \begin{syntax}
+%     \cs{box_ht:N} \meta{box}
+%   \end{syntax}
+%   Calculates the height (above the baseline) of the \meta{box}
+%   in a form suitable for use in a \meta{dim expr}.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{ht}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}{\box_wd:N, \box_wd:c}
+%   \begin{syntax}
+%     \cs{box_wd:N} \meta{box}
+%   \end{syntax}
+%   Calculates the width of the \meta{box} in a form
+%   suitable for use in a \meta{dim expr}.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{wd}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2021-05-05]{\box_ht_plus_dp:N, \box_ht_plus_dp:c}
+%   \begin{syntax}
+%     \cs{box_ht_plus_dp:N} \meta{box}
+%   \end{syntax}
+%   Calculates the total vertical size (height plus depth) of the \meta{box}
+%   in a form suitable for use in a \meta{dim expr}.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \box_set_dp:Nn, \box_set_dp:cn,
+%     \box_gset_dp:Nn, \box_gset_dp:cn
+%   }
+%   \begin{syntax}
+%     \cs{box_set_dp:Nn} \meta{box} \Arg{dim expr}
+%   \end{syntax}
+%   Set the depth (below the baseline) of the \meta{box} to the value of
+%   the \Arg{dim expr}.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \box_set_ht:Nn, \box_set_ht:cn,
+%     \box_gset_ht:Nn, \box_gset_ht:cn
+%   }
+%   \begin{syntax}
+%     \cs{box_set_ht:Nn} \meta{box} \Arg{dim expr}
+%   \end{syntax}
+%   Set the height (above the baseline) of the \meta{box} to the value of
+%   the \Arg{dim expr}.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \box_set_wd:Nn, \box_set_wd:cn,
+%     \box_gset_wd:Nn, \box_gset_wd:cn
+%   }
+%   \begin{syntax}
+%     \cs{box_set_wd:Nn} \meta{box} \Arg{dim expr}
+%   \end{syntax}
+%   Set the width of the \meta{box} to the value of the
+%   \Arg{dim expr}.
+% \end{function}
+%
+% \section{Box conditionals}
+%
+% \begin{function}[EXP,pTF]{\box_if_empty:N, \box_if_empty:c}
+%   \begin{syntax}
+%     \cs{box_if_empty_p:N} \meta{box}
+%     \cs{box_if_empty:NTF} \meta{box} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests if \meta{box} is a empty (equal to \cs{c_empty_box}).
+% \end{function}
+%
+% \begin{function}[EXP,pTF]{\box_if_horizontal:N, \box_if_horizontal:c}
+%   \begin{syntax}
+%     \cs{box_if_horizontal_p:N} \meta{box}
+%     \cs{box_if_horizontal:NTF} \meta{box} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests if \meta{box} is a horizontal box.
+% \end{function}
+%
+% \begin{function}[EXP,pTF]{\box_if_vertical:N, \box_if_vertical:c}
+%   \begin{syntax}
+%     \cs{box_if_vertical_p:N} \meta{box}
+%     \cs{box_if_vertical:NTF} \meta{box} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests if \meta{box} is a vertical box.
+% \end{function}
+%
+% \section{The last box inserted}
+%
+% \begin{function}
+%   {
+%     \box_set_to_last:N,  \box_set_to_last:c,
+%     \box_gset_to_last:N, \box_gset_to_last:c
+%   }
+%   \begin{syntax}
+%     \cs{box_set_to_last:N} \meta{box}
+%   \end{syntax}
+%   Sets the \meta{box} equal to the last item (box) added to the current
+%   partial list, removing the item from the list at the same time. When
+%   applied to the main vertical list, the \meta{box} is always void as
+%   it is not possible to recover the last added item.
+% \end{function}
+%
+% \section{Constant boxes}
+%
+% \begin{variable}[updated = 2012-11-04]{\c_empty_box}
+%   This is a permanently empty box, which is neither set as horizontal
+%   nor vertical.
+%   \begin{texnote}
+%     At the \TeX{} level this is a void box.
+%   \end{texnote}
+% \end{variable}
+%
+% \section{Scratch boxes}
+%
+% \begin{variable}[updated = 2012-11-04]{\l_tmpa_box, \l_tmpb_box}
+%   Scratch boxes for local assignment. These are never used by
+%   the kernel code, and so are safe for use with any \LaTeX3-defined
+%   function. However, they may be overwritten by other non-kernel
+%   code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}{\g_tmpa_box, \g_tmpb_box}
+%   Scratch boxes for global assignment. These are never used by
+%   the kernel code, and so are safe for use with any \LaTeX3-defined
+%   function. However, they may be overwritten by other non-kernel
+%   code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \section{Viewing box contents}
+%
+% \begin{function}[updated = 2012-05-11]{\box_show:N, \box_show:c}
+%   \begin{syntax}
+%      \cs{box_show:N} \meta{box}
+%   \end{syntax}
+%   Shows full details of the content of the \meta{box} in the terminal.
+% \end{function}
+%
+% \begin{function}[added = 2012-05-11]{\box_show:Nnn, \box_show:cnn}
+%   \begin{syntax}
+%      \cs{box_show:Nnn} \meta{box} \Arg{int expr_1} \Arg{int expr_2}
+%   \end{syntax}
+%   Display the contents of \meta{box} in the terminal, showing the first
+%   \meta{int expr_1} items of the box, and descending into \meta{int expr_2}
+%   group levels.
+% \end{function}
+%
+% \begin{function}[added = 2012-05-11]{\box_log:N, \box_log:c}
+%   \begin{syntax}
+%      \cs{box_log:N} \meta{box}
+%   \end{syntax}
+%   Writes full details of the content of the \meta{box} to the log.
+% \end{function}
+%
+% \begin{function}[added = 2012-05-11]{\box_log:Nnn, \box_log:cnn}
+%   \begin{syntax}
+%      \cs{box_log:Nnn} \meta{box} \Arg{int expr_1} \Arg{int expr_2}
+%   \end{syntax}
+%   Writes the contents of \meta{box} to the log, showing the first
+%   \meta{int expr_1} items of the box, and descending into \meta{int expr_2}
+%   group levels.
+% \end{function}
+%
+% \section{Boxes and color}
+%
+% All \LaTeX{}3 boxes are \enquote{color safe}: a color set inside the box
+% stops applying after the end of the box has occurred.
+%
+% \section{Horizontal mode boxes}
+%
+% \begin{function}[updated = 2017-04-05]{\hbox:n}
+%   \begin{syntax}
+%     \cs{hbox:n} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a horizontal box of natural
+%   width and then includes this box in the current list for typesetting.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]{\hbox_to_wd:nn}
+%   \begin{syntax}
+%     \cs{hbox_to_wd:nn} \Arg{dim expr} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a horizontal box of width
+%   \meta{dim expr} and then includes this box in the current list for
+%   typesetting.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]{\hbox_to_zero:n}
+%   \begin{syntax}
+%     \cs{hbox_to_zero:n} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a horizontal box of zero width
+%   and then includes this box in the current list for typesetting.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]
+%   {\hbox_set:Nn, \hbox_set:cn, \hbox_gset:Nn, \hbox_gset:cn}
+%   \begin{syntax}
+%     \cs{hbox_set:Nn} \meta{box} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} at natural width and then stores the
+%   result inside the \meta{box}.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]
+%   {
+%     \hbox_set_to_wd:Nnn,  \hbox_set_to_wd:cnn,
+%     \hbox_gset_to_wd:Nnn, \hbox_gset_to_wd:cnn
+%   }
+%   \begin{syntax}
+%     \cs{hbox_set_to_wd:Nnn} \meta{box} \Arg{dim expr} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} to the width given by the \meta{dim expr}
+%   and then stores the result inside the \meta{box}.
+% \end{function}
+%
+% \begin{function}[added = 2020-08-25]{\hbox_overlap_center:n}
+%   \begin{syntax}
+%     \cs{hbox_overlap_center:n} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a horizontal box of zero width
+%   such that material protrudes equally to both sides of the insertion point.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]{\hbox_overlap_right:n}
+%   \begin{syntax}
+%     \cs{hbox_overlap_right:n} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a horizontal box of zero width
+%   such that material protrudes to the right of the insertion point.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]{\hbox_overlap_left:n}
+%   \begin{syntax}
+%     \cs{hbox_overlap_left:n} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a horizontal box of zero width
+%   such that material protrudes to the left of the insertion point.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]
+%   {
+%     \hbox_set:Nw, \hbox_set:cw,
+%     \hbox_set_end:,
+%     \hbox_gset:Nw, \hbox_gset:cw,
+%     \hbox_gset_end:
+%   }
+%   \begin{syntax}
+%     \cs{hbox_set:Nw} \meta{box} \meta{contents} \cs{hbox_set_end:}
+%   \end{syntax}
+%   Typesets the \meta{contents} at natural width and then stores the
+%   result inside the \meta{box}. In contrast
+%   to \cs{hbox_set:Nn} this function does not absorb the argument
+%   when finding the \meta{content}, and so can be used in circumstances
+%   where the \meta{content} may not be a simple argument.
+% \end{function}
+%
+% \begin{function}[added = 2017-06-08]
+%   {
+%     \hbox_set_to_wd:Nnw,  \hbox_set_to_wd:cnw,
+%     \hbox_gset_to_wd:Nnw, \hbox_gset_to_wd:cnw
+%   }
+%   \begin{syntax}
+%     \cs{hbox_set_to_wd:Nnw} \meta{box} \Arg{dim expr} \meta{contents} \cs{hbox_set_end:}
+%   \end{syntax}
+%   Typesets the \meta{contents} to the width given by the \meta{dim expr}
+%   and then stores the result inside the \meta{box}. In contrast
+%   to \cs{hbox_set_to_wd:Nnn} this function does not absorb the argument
+%   when finding the \meta{content}, and so can be used in circumstances
+%   where the \meta{content} may not be a simple argument
+% \end{function}
+%
+% \begin{function}{\hbox_unpack:N, \hbox_unpack:c}
+%   \begin{syntax}
+%     \cs{hbox_unpack:N} \meta{box}
+%   \end{syntax}
+%   Unpacks the content of the horizontal \meta{box}, retaining any stretching
+%   or shrinking applied when the \meta{box} was set.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{unhcopy}.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Vertical mode boxes}
+%
+% Vertical boxes inherit their baseline from their contents. The
+% standard case is that the baseline of the box is at the same position
+% as that of the last item added to the box. This means that the box
+% has no depth unless the last item added to it had depth. As a
+% result most vertical boxes have a large height value and small or
+% zero depth. The exception are |_top| boxes, where the reference point
+% is that of the first item added. These tend to have a large depth and
+% small height, although the latter is typically non-zero.
+%
+% \begin{function}[updated = 2017-04-05]{\vbox:n}
+%   \begin{syntax}
+%     \cs{vbox:n} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a vertical box of natural height
+%   and includes this box in the current list for typesetting.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]{\vbox_top:n}
+%   \begin{syntax}
+%     \cs{vbox_top:n} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a vertical box of natural height
+%   and includes this box in the current list for typesetting. The
+%   baseline of the box is equal to that of the \emph{first}
+%   item added to the box.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]{\vbox_to_ht:nn}
+%   \begin{syntax}
+%     \cs{vbox_to_ht:nn} \Arg{dim expr} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a vertical box of height
+%   \meta{dim expr} and then includes this box in the current list for
+%   typesetting.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]{\vbox_to_zero:n}
+%   \begin{syntax}
+%     \cs{vbox_to_zero:n} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} into a vertical box of zero height
+%   and then includes this box in the current list for typesetting.
+% \end{function}
+%
+%  \begin{function}[updated = 2017-04-05]
+%    {\vbox_set:Nn, \vbox_set:cn, \vbox_gset:Nn, \vbox_gset:cn}
+%   \begin{syntax}
+%     \cs{vbox_set:Nn} \meta{box} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} at natural height and then stores the
+%   result inside the \meta{box}.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]
+%   {\vbox_set_top:Nn, \vbox_set_top:cn, \vbox_gset_top:Nn, \vbox_gset_top:cn}
+%   \begin{syntax}
+%     \cs{vbox_set_top:Nn} \meta{box} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} at natural height and then stores the
+%   result inside the \meta{box}. The baseline of the box is equal
+%   to that of the \emph{first} item added to the box.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]
+%   {
+%     \vbox_set_to_ht:Nnn,  \vbox_set_to_ht:cnn,
+%     \vbox_gset_to_ht:Nnn, \vbox_gset_to_ht:cnn
+%   }
+%   \begin{syntax}
+%     \cs{vbox_set_to_ht:Nnn} \meta{box} \Arg{dim expr} \Arg{contents}
+%   \end{syntax}
+%   Typesets the \meta{contents} to the height given by the
+%   \meta{dim expr} and then stores the result inside the \meta{box}.
+% \end{function}
+%
+% \begin{function}[updated = 2017-04-05]
+%   {
+%     \vbox_set:Nw, \vbox_set:cw,
+%     \vbox_set_end:,
+%     \vbox_gset:Nw, \vbox_gset:cw,
+%     \vbox_gset_end:
+%   }
+%   \begin{syntax}
+%     \cs{vbox_set:Nw} \meta{box} \meta{contents} \cs{vbox_set_end:}
+%   \end{syntax}
+%   Typesets the \meta{contents} at natural height and then stores the
+%   result inside the \meta{box}. In contrast
+%   to \cs{vbox_set:Nn} this function does not absorb the argument
+%   when finding the \meta{content}, and so can be used in circumstances
+%   where the \meta{content} may not be a simple argument.
+% \end{function}
+%
+% \begin{function}[added = 2017-06-08]
+%   {
+%     \vbox_set_to_ht:Nnw,  \vbox_set_to_ht:cnw,
+%     \vbox_gset_to_ht:Nnw, \vbox_gset_to_ht:cnw
+%   }
+%   \begin{syntax}
+%     \cs{vbox_set_to_ht:Nnw} \meta{box} \Arg{dim expr} \meta{contents} \cs{vbox_set_end:}
+%   \end{syntax}
+%   Typesets the \meta{contents} to the height given by the \meta{dim expr}
+%   and then stores the result inside the \meta{box}. In contrast
+%   to \cs{vbox_set_to_ht:Nnn} this function does not absorb the argument
+%   when finding the \meta{content}, and so can be used in circumstances
+%   where the \meta{content} may not be a simple argument
+% \end{function}
+%
+%
+% \begin{function}[updated = 2018-12-29]
+%   {
+%     \vbox_set_split_to_ht:NNn, \vbox_set_split_to_ht:cNn,
+%     \vbox_set_split_to_ht:Ncn, \vbox_set_split_to_ht:ccn,
+%     \vbox_gset_split_to_ht:NNn, \vbox_gset_split_to_ht:cNn,
+%     \vbox_gset_split_to_ht:Ncn, \vbox_gset_split_to_ht:ccn
+%   }
+%   \begin{syntax}
+%      \cs{vbox_set_split_to_ht:NNn} \meta{box_1} \meta{box_2} \Arg{dim expr}
+%   \end{syntax}
+%   Sets \meta{box_1} to contain material to the height given by the
+%   \meta{dim expr} by removing content from the top of \meta{box_2}
+%   (which must be a vertical box).
+% \end{function}
+%
+% \begin{function}{\vbox_unpack:N, \vbox_unpack:c}
+%   \begin{syntax}
+%     \cs{vbox_unpack:N} \meta{box}
+%   \end{syntax}
+%   Unpacks the content of the vertical \meta{box}, retaining any stretching
+%   or shrinking applied when the \meta{box} was set.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{unvcopy}.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Using boxes efficiently}
+%
+% The functions above for using box contents work in exactly the same
+% way as for any other \pkg{expl3} variable. However, for efficiency
+% reasons, it is also useful to have functions which \emph{drop} box
+% contents on use. When a box is dropped, the box becomes empty at the group
+% level \emph{where the box was originally set} rather than necessarily
+% \emph{at the current group level}. For example, with
+% \begin{verbatim}
+%   \hbox_set:Nn \l_tmpa_box { A }
+%   \group_begin:
+%     \hbox_set:Nn \l_tmpa_box { B }
+%      \group_begin:
+%      \box_use_drop:N \l_tmpa_box
+%     \group_end:
+%     \box_show:N \l_tmpa_box
+%   \group_end:
+%   \box_show:N \l_tmpa_box
+%   \end{verbatim}
+% the first use of \cs{box_show:N} will show an entirely cleared (void) box, and the
+% second will show the letter |A| in the box.
+%
+% These functions should be preferred when the content of the box is no
+% longer required after use. Note that due to the unusual scoping behaviour of
+% \texttt{drop} functions they may be applied to both local and global boxes:
+% the latter will naturally be set and thus cleared at a global level.
+%
+% \begin{function}{\box_use_drop:N, \box_use_drop:c}
+%   \begin{syntax}
+%     \cs{box_use_drop:N} \meta{box}
+%   \end{syntax}
+%   Inserts the current content of the \meta{box} onto the current
+%   list for typesetting then drops the box content.  An error is raised if the
+%   variable does not exist or if it is invalid. This function may be applied to
+%   local or global boxes.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{box}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2019-01-17]
+%   {
+%     \box_set_eq_drop:NN, \box_set_eq_drop:cN,
+%     \box_set_eq_drop:Nc, \box_set_eq_drop:cc
+%   }
+%   \begin{syntax}
+%     \cs{box_set_eq_drop:NN} \meta{box_1} \meta{box_2}
+%   \end{syntax}
+%   Sets the content of \meta{box_1} equal to that of \meta{box_2}, then
+%   drops \meta{box_2}.
+% \end{function}
+%
+% \begin{function}[added = 2019-01-17]
+%   {
+%     \box_gset_eq_drop:NN, \box_gset_eq_drop:cN,
+%     \box_gset_eq_drop:Nc, \box_gset_eq_drop:cc
+%   }
+%   \begin{syntax}
+%     \cs{box_gset_eq_drop:NN} \meta{box_1} \meta{box_2}
+%   \end{syntax}
+%   Sets the content of \meta{box_1} globally equal to that of \meta{box_2},
+%   then drops \meta{box_2}.
+% \end{function}
+%
+% \begin{function}[added = 2019-01-17]
+%   {\hbox_unpack_drop:N, \hbox_unpack_drop:c}
+%   \begin{syntax}
+%     \cs{hbox_unpack_drop:N} \meta{box}
+%   \end{syntax}
+%   Unpacks the content of the horizontal \meta{box}, retaining any stretching
+%   or shrinking applied when the \meta{box} was set. The original \meta{box}
+%   is then dropped.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{unhbox}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2019-01-17]
+%   {\vbox_unpack_drop:N, \vbox_unpack_drop:c}
+%   \begin{syntax}
+%     \cs{vbox_unpack_drop:N} \meta{box}
+%   \end{syntax}
+%   Unpacks the content of the vertical \meta{box}, retaining any stretching
+%   or shrinking applied when the \meta{box} was set. The original \meta{box}
+%   is then dropped.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{unvbox}.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Affine transformations}
+%
+% Affine transformations are changes which (informally) preserve straight
+% lines. Simple translations are affine transformations, but are better handled
+% in \TeX{} by doing the translation first, then inserting an unmodified box.
+% On the other hand, rotation and resizing of boxed material can best be
+% handled by modifying boxes. These transformations are described here.
+%
+% \begin{function}[added = 2017-04-04, updated = 2019-01-22]
+%   {
+%     \box_autosize_to_wd_and_ht:Nnn, \box_autosize_to_wd_and_ht:cnn,
+%     \box_gautosize_to_wd_and_ht:Nnn, \box_gautosize_to_wd_and_ht:cnn,
+%   }
+%   \begin{syntax}
+%     \cs{box_autosize_to_wd_and_ht:Nnn} \meta{box} \Arg{x-size} \Arg{y-size}
+%   \end{syntax}
+%   Resizes the \meta{box} to fit within the given \meta{x-size} (horizontally)
+%   and \meta{y-size} (vertically); both of the sizes are dimension
+%   expressions. The \meta{y-size} is the height only: it does not include any
+%   depth. The updated \meta{box} is an |hbox|, irrespective of the nature
+%   of the \meta{box} before the resizing is applied. The final size of the
+%   \meta{box} is the smaller of \Arg{x-size} and \Arg{y-size},
+%   \emph{i.e.}~the result fits within the dimensions specified. Negative
+%   sizes cause the material in the \meta{box} to be reversed in direction,
+%   but the reference point of the \meta{box} is unchanged. Thus a negative
+%   \meta{y-size} results in the \meta{box} having a depth dependent on the
+%   height of the original and \emph{vice versa}.
+% \end{function}
+%
+% \begin{function}[added = 2017-04-04, updated = 2019-01-22]
+%   {
+%     \box_autosize_to_wd_and_ht_plus_dp:Nnn,
+%     \box_autosize_to_wd_and_ht_plus_dp:cnn,
+%     \box_gautosize_to_wd_and_ht_plus_dp:Nnn,
+%     \box_gautosize_to_wd_and_ht_plus_dp:cnn
+%   }
+%   \begin{syntax}
+%     \cs{box_autosize_to_wd_and_ht_plus_dp:Nnn} \meta{box} \Arg{x-size} \Arg{y-size}
+%   \end{syntax}
+%   Resizes the \meta{box} to fit within the given \meta{x-size} (horizontally)
+%   and \meta{y-size} (vertically); both of the sizes are dimension
+%   expressions. The \meta{y-size} is the total vertical size (height plus
+%   depth). The updated \meta{box} is an |hbox|, irrespective of the nature
+%   of the \meta{box} before the resizing is applied. The final size of the
+%   \meta{box} is the smaller of \Arg{x-size} and \Arg{y-size},
+%   \emph{i.e.}~the result fits within the dimensions specified. Negative
+%   sizes cause the material in the \meta{box} to be reversed in direction,
+%   but the reference point of the \meta{box} is unchanged. Thus a negative
+%   \meta{y-size} results in the \meta{box} having a depth dependent on the
+%   height of the original and \emph{vice versa}.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \box_resize_to_ht:Nn, \box_resize_to_ht:cn,
+%     \box_gresize_to_ht:Nn, \box_gresize_to_ht:cn
+%   }
+%   \begin{syntax}
+%     \cs{box_resize_to_ht:Nn} \meta{box} \Arg{y-size}
+%   \end{syntax}
+%   Resizes the \meta{box} to \meta{y-size} (vertically), scaling the horizontal
+%   size by the same amount; \meta{y-size} is a dimension expression. The
+%   \meta{y-size} is the height only: it does not include any depth. The updated
+%   \meta{box} is an |hbox|, irrespective of the nature of the \meta{box}
+%   before the resizing is applied. A negative \meta{y-size} causes the
+%   material in the \meta{box} to be reversed in direction, but the reference
+%   point of the \meta{box} is unchanged. Thus a negative \meta{y-size}
+%   results in the \meta{box} having a depth dependent on the height of the
+%   original and \emph{vice versa}.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn,
+%     \box_gresize_to_ht_plus_dp:Nn, \box_gresize_to_ht_plus_dp:cn,
+%   }
+%   \begin{syntax}
+%     \cs{box_resize_to_ht_plus_dp:Nn} \meta{box} \Arg{y-size}
+%   \end{syntax}
+%   Resizes the \meta{box} to \meta{y-size} (vertically), scaling the horizontal
+%   size by the same amount; \meta{y-size} is a dimension expression. The
+%   \meta{y-size} is the total vertical size (height plus depth). The updated
+%   \meta{box} is an |hbox|, irrespective of the nature of the \meta{box}
+%   before the resizing is applied. A negative \meta{y-size} causes
+%   the material in the \meta{box} to be reversed in direction, but the
+%   reference point of the \meta{box} is unchanged. Thus a negative
+%   \meta{y-size} results in the \meta{box} having a depth dependent on the
+%   height of the original and \emph{vice versa}.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \box_resize_to_wd:Nn, \box_resize_to_wd:cn,
+%     \box_gresize_to_wd:Nn, \box_gresize_to_wd:cn
+%   }
+%   \begin{syntax}
+%     \cs{box_resize_to_wd:Nn} \meta{box} \Arg{x-size}
+%   \end{syntax}
+%   Resizes the \meta{box} to \meta{x-size} (horizontally), scaling the vertical
+%   size by the same amount; \meta{x-size} is a dimension expression. The updated
+%   \meta{box} is an |hbox|, irrespective of the nature of the \meta{box}
+%   before the resizing is applied. A negative \meta{x-size} causes the
+%   material in the \meta{box} to be reversed in direction, but the reference
+%   point of the \meta{box} is unchanged. Thus a negative \meta{x-size}
+%   results in the \meta{box} having a depth dependent on the height of the
+%   original and \emph{vice versa}.
+% \end{function}
+%
+% \begin{function}[added = 2014-07-03, updated = 2019-01-22]
+%   {
+%     \box_resize_to_wd_and_ht:Nnn, \box_resize_to_wd_and_ht:cnn,
+%     \box_gresize_to_wd_and_ht:Nnn, \box_gresize_to_wd_and_ht:cnn
+%   }
+%   \begin{syntax}
+%     \cs{box_resize_to_wd_and_ht:Nnn} \meta{box} \Arg{x-size} \Arg{y-size}
+%   \end{syntax}
+%   Resizes the \meta{box} to \meta{x-size} (horizontally) and \meta{y-size}
+%   (vertically): both of the sizes are dimension expressions. The
+%   \meta{y-size} is the height only and does not include any depth. The updated
+%   \meta{box} is an |hbox|, irrespective of the nature of the \meta{box}
+%   before the resizing is applied. Negative sizes cause the material in
+%   the \meta{box} to be reversed in direction, but the reference point of the
+%   \meta{box} is unchanged. Thus a negative \meta{y-size} results in
+%   the \meta{box} having a depth dependent on the height of the original and
+%   \emph{vice versa}.
+% \end{function}
+%
+% \begin{function}[added = 2017-04-06, updated = 2019-01-22]
+%   {
+%     \box_resize_to_wd_and_ht_plus_dp:Nnn,
+%     \box_resize_to_wd_and_ht_plus_dp:cnn,
+%     \box_gresize_to_wd_and_ht_plus_dp:Nnn,
+%     \box_gresize_to_wd_and_ht_plus_dp:cnn
+%   }
+%   \begin{syntax}
+%     \cs{box_resize_to_wd_and_ht_plus_dp:Nnn} \meta{box} \Arg{x-size} \Arg{y-size}
+%   \end{syntax}
+%   Resizes the \meta{box} to \meta{x-size} (horizontally) and \meta{y-size}
+%   (vertically): both of the sizes are dimension expressions. The
+%   \meta{y-size} is the total vertical size (height plus depth). The updated
+%   \meta{box} is an |hbox|, irrespective of the nature of the \meta{box}
+%   before the resizing is applied. Negative sizes cause the material in
+%   the \meta{box} to be reversed in direction, but the reference point of the
+%   \meta{box} is unchanged. Thus a negative \meta{y-size} results in
+%   the \meta{box} having a depth dependent on the height of the original and
+%   \emph{vice versa}.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \box_rotate:Nn, \box_rotate:cn,
+%     \box_grotate:Nn, \box_grotate:cn
+%   }
+%   \begin{syntax}
+%     \cs{box_rotate:Nn} \meta{box} \Arg{angle}
+%   \end{syntax}
+%   Rotates the \meta{box} by \meta{angle} (a \meta{fp expr} in degrees)
+%   anti-clockwise about
+%   its reference point. The reference point of the updated box is moved
+%   horizontally such that it is at the left side of the smallest rectangle
+%   enclosing the rotated material. The updated \meta{box} is an |hbox|,
+%   irrespective of the nature of the \meta{box} before the rotation is applied.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \box_scale:Nnn, \box_scale:cnn,
+%     \box_gscale:Nnn, \box_gscale:cnn
+%   }
+%   \begin{syntax}
+%     \cs{box_scale:Nnn} \meta{box} \Arg{x-scale} \Arg{y-scale}
+%   \end{syntax}
+%   Scales the \meta{box} by factors \meta{x-scale} and \meta{y-scale} in
+%   the horizontal and vertical directions, respectively (both scales are
+%   \meta{fp expr}). The updated \meta{box} is an |hbox|, irrespective
+%   of the nature of the \meta{box} before the scaling is applied. Negative
+%   scalings cause the material in the \meta{box} to be reversed in
+%   direction, but the reference point of the \meta{box} is unchanged.
+%   Thus a negative \meta{y-scale} results in the \meta{box} having a depth
+%   dependent on the height of the original and \emph{vice versa}.
+% \end{function}
+%
+% \section{Viewing part of a box}
+%
+% \begin{function}[updated = 2023-04-14]
+%   {
+%     \box_set_clipped:N, \box_set_clipped:c,
+%     \box_gset_clipped:N, \box_gset_clipped:c
+%   }
+%   \begin{syntax}
+%     \cs{box_set_clipped:N} \meta{box}
+%   \end{syntax}
+%   Clips the \meta{box} in the output so that only material inside the
+%   bounding box is displayed in the output. The updated \meta{box} is an
+%   hbox, irrespective of the nature of the \meta{box} before the clipping is
+%   applied. Additional box levels are also generated by this operation.
+%
+%   \begin{texnote}
+%     Clipping is implemented by the driver, and as such the full content of
+%     the box is placed in the output file. Thus clipping does not remove
+%     any information from the raw output, and hidden material can therefore
+%     be viewed by direct examination of the file.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2019-01-23]
+%   {
+%     \box_set_trim:Nnnnn, \box_set_trim:cnnnn,
+%     \box_gset_trim:Nnnnn, \box_gset_trim:cnnnn
+%   }
+%   \begin{syntax}
+%     \cs{box_set_trim:Nnnnn} \meta{box} \Arg{left} \Arg{bottom} \Arg{right} \Arg{top}
+%   \end{syntax}
+%   Adjusts the bounding box of the \meta{box} \meta{left} is removed from
+%   the left-hand edge of the bounding box, \meta{right} from the right-hand
+%   edge and so fourth. All adjustments are \meta{dim exprs}.
+%   Material outside of the bounding box is still displayed in the output
+%   unless \cs{box_set_clipped:N} is subsequently applied.
+%   The updated \meta{box} is an
+%   hbox, irrespective of the nature of the \meta{box} before the trim
+%   operation is applied.
+%   Additional box levels are also generated by this operation.
+%   The behavior of the operation where the trims requested is
+%   greater than the size of the box is undefined.
+% \end{function}
+%
+% \begin{function}[added = 2019-01-23]
+%   {
+%     \box_set_viewport:Nnnnn, \box_set_viewport:cnnnn,
+%     \box_gset_viewport:Nnnnn, \box_gset_viewport:cnnnn
+%   }
+%   \begin{syntax}
+%     \cs{box_set_viewport:Nnnnn} \meta{box} \Arg{llx} \Arg{lly} \Arg{urx} \Arg{ury}
+%   \end{syntax}
+%   Adjusts the bounding box of the \meta{box} such that it has lower-left
+%   co-ordinates (\meta{llx}, \meta{lly}) and upper-right co-ordinates
+%   (\meta{urx}, \meta{ury}). All four co-ordinate positions are
+%   \meta{dim exprs}. Material outside of the bounding box is
+%   still displayed in the output unless \cs{box_set_clipped:N} is
+%   subsequently applied.
+%   The updated \meta{box} is an
+%   hbox, irrespective of the nature of the \meta{box} before the viewport
+%   operation is applied.
+%   Additional box levels are also generated by this operation.
+% \end{function}
+%
+% \section{Primitive box conditionals}
+%
+% \begin{function}[EXP]{\if_hbox:N}
+%   \begin{syntax}
+%     \cs{if_hbox:N} \meta{box}
+%     ~~\meta{true code}
+%     \cs{else:}
+%     ~~\meta{false code}
+%     \cs{fi:}
+%   \end{syntax}
+%   Tests is \meta{box} is a horizontal box.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{ifhbox}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\if_vbox:N}
+%   \begin{syntax}
+%     \cs{if_vbox:N} \meta{box}
+%     ~~\meta{true code}
+%     \cs{else:}
+%     ~~\meta{false code}
+%     \cs{fi:}
+%   \end{syntax}
+%   Tests is \meta{box} is a vertical box.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{ifvbox}.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\if_box_empty:N}
+%   \begin{syntax}
+%     \cs{if_box_empty:N} \meta{box}
+%     ~~\meta{true code}
+%     \cs{else:}
+%     ~~\meta{false code}
+%     \cs{fi:}
+%   \end{syntax}
+%   Tests is \meta{box} is an empty (void) box.
+%   \begin{texnote}
+%     This is the \TeX{} primitive \tn{ifvoid}.
+%   \end{texnote}
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3box} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=box>
+%    \end{macrocode}
+%
+% \subsection{Support code}
+%
+% \begin{macro}{\@@_dim_eval:w}
+% \begin{macro}{\@@_dim_eval:n}
+%   Evaluating a dimension expression expandably. The only
+%   difference with \cs{dim_eval:n} is the lack of \cs{dim_use:N}, to
+%   produce an internal dimension rather than expand it into characters.
+%    \begin{macrocode}
+\cs_new_eq:NN \@@_dim_eval:w \tex_dimexpr:D
+\cs_new:Npn \@@_dim_eval:n #1
+  { \@@_dim_eval:w #1 \scan_stop: }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\__kernel_kern:n}
+%   We need kerns in a few places. At present, we don't have a module for
+%   this concept, so it goes in at first use: here. The idea is to avoid
+%   repeated use of the bare primitive.
+%    \begin{macrocode}
+\cs_new_protected:Npn \__kernel_kern:n #1
+  { \tex_kern:D \@@_dim_eval:n {#1} }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Creating and initialising boxes}
+%
+% \TestFiles{m3box001.lvt}
+%
+% \begin{macro}{\box_new:N, \box_new:c}
+%   Defining a new \meta{box} register: remember that box $255$ is not
+%   generally available.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_new:N #1
+  {
+    \__kernel_chk_if_free_cs:N #1
+    \cs:w newbox \cs_end: #1
+  }
+\cs_generate_variant:Nn \box_new:N { c }
+%    \end{macrocode}
+%
+% \begin{macro}{\box_clear:N, \box_clear:c}
+% \begin{macro}{\box_gclear:N, \box_gclear:c}
+% \testfile*
+%   Clear a \meta{box} register.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_clear:N #1
+  { \box_set_eq:NN  #1 \c_empty_box }
+\cs_new_protected:Npn \box_gclear:N #1
+  { \box_gset_eq:NN #1 \c_empty_box }
+\cs_generate_variant:Nn \box_clear:N  { c }
+\cs_generate_variant:Nn \box_gclear:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\box_clear_new:N, \box_clear_new:c}
+% \begin{macro}{\box_gclear_new:N, \box_gclear_new:c}
+% \testfile*
+%   Clear or new.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_clear_new:N #1
+  { \box_if_exist:NTF #1 { \box_clear:N #1 } { \box_new:N #1 } }
+\cs_new_protected:Npn \box_gclear_new:N #1
+  { \box_if_exist:NTF #1 { \box_gclear:N #1 } { \box_new:N #1 } }
+\cs_generate_variant:Nn \box_clear_new:N  { c }
+\cs_generate_variant:Nn \box_gclear_new:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%  \begin{macro}
+%    {\box_set_eq:NN, \box_set_eq:cN, \box_set_eq:Nc, \box_set_eq:cc}
+% \testfile*
+%  \begin{macro}
+%    {\box_gset_eq:NN, \box_gset_eq:cN, \box_gset_eq:Nc, \box_gset_eq:cc}
+% \testfile*
+%   Assigning the contents of a box to be another box.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_set_eq:NN #1#2
+  { \tex_setbox:D #1 \tex_copy:D #2 }
+\cs_new_protected:Npn \box_gset_eq:NN #1#2
+  { \tex_global:D \tex_setbox:D #1 \tex_copy:D #2 }
+\cs_generate_variant:Nn \box_set_eq:NN  { c , Nc , cc }
+\cs_generate_variant:Nn \box_gset_eq:NN { c , Nc , cc }
+%    \end{macrocode}
+%  \end{macro}
+%  \end{macro}
+%
+% \begin{macro}
+%   {
+%     \box_set_eq_drop:NN, \box_set_eq_drop:cN,
+%     \box_set_eq_drop:Nc, \box_set_eq_drop:cc
+%   }
+% \begin{macro}
+%   {
+%     \box_gset_eq_drop:NN, \box_gset_eq_drop:cN,
+%     \box_gset_eq_drop:Nc, \box_gset_eq_drop:cc
+%   }
+%    Assigning the contents of a box to be another box, then drops the
+%    original box.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_set_eq_drop:NN #1#2
+  { \tex_setbox:D #1 \tex_box:D #2 }
+\cs_new_protected:Npn \box_gset_eq_drop:NN #1#2
+  { \tex_global:D \tex_setbox:D #1 \tex_box:D #2 }
+\cs_generate_variant:Nn \box_set_eq_drop:NN  { c , Nc , cc }
+\cs_generate_variant:Nn \box_gset_eq_drop:NN { c , Nc , cc }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\box_if_exist:N, \box_if_exist:c}
+%   Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
+%    \begin{macrocode}
+\prg_new_eq_conditional:NNn \box_if_exist:N \cs_if_exist:N
+  { TF , T , F , p }
+\prg_new_eq_conditional:NNn \box_if_exist:c \cs_if_exist:c
+  { TF , T , F , p }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Measuring and setting box dimensions}
+%
+% \begin{macro}{\box_ht:N, \box_ht:c}
+% \begin{macro}{\box_dp:N, \box_dp:c}
+% \begin{macro}{\box_wd:N, \box_wd:c}
+% \testfile*
+%    Accessing the height, depth, and width of a \meta{box} register.
+%    \begin{macrocode}
+\cs_new_eq:NN \box_ht:N \tex_ht:D
+\cs_new_eq:NN \box_dp:N \tex_dp:D
+\cs_new_eq:NN \box_wd:N \tex_wd:D
+\cs_generate_variant:Nn \box_ht:N { c }
+\cs_generate_variant:Nn \box_dp:N { c }
+\cs_generate_variant:Nn \box_wd:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\box_ht_plus_dp:N}
+%   The \cs{box_ht:N} and \cs{box_dp:N} primitives do not expand but
+%   rather are suitable for use after \tn{the} or inside dimension
+%   expressions.  Here we obtain the same behaviour by using
+%   \cs{@@_dim_eval:n} (basically \tn{dimexpr}) rather than
+%   \cs{dim_eval:n} (basically \tn{the} \tn{dimexpr}).
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_ht_plus_dp:N #1
+  { \@@_dim_eval:n { \box_ht:N #1 + \box_dp:N #1 } }
+\cs_generate_variant:Nn \box_ht_plus_dp:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\box_set_ht:Nn, \box_set_ht:cn, \box_gset_ht:Nn, \box_gset_ht:cn}
+% \begin{macro}{\box_set_dp:Nn, \box_set_dp:cn, \box_gset_dp:Nn, \box_gset_dp:cn}
+% \begin{macro}{\box_set_wd:Nn, \box_set_wd:cn, \box_gset_wd:Nn, \box_gset_wd:cn}
+%   Setting the size whilst respecting local scope requires copying;
+%   the same issue does not come up when working globally.
+%   When debugging, the dimension expression |#2| is surrounded by
+%   parentheses to catch early termination.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_set_dp:Nn #1#2
+  {
+    \tex_setbox:D #1 = \tex_copy:D #1
+    \box_dp:N #1 \@@_dim_eval:n {#2}
+  }
+\cs_generate_variant:Nn \box_set_dp:Nn { c }
+\cs_new_protected:Npn \box_gset_dp:Nn #1#2
+  { \box_dp:N #1 \@@_dim_eval:n {#2} }
+\cs_generate_variant:Nn \box_gset_dp:Nn { c }
+\cs_new_protected:Npn \box_set_ht:Nn #1#2
+  {
+    \tex_setbox:D #1 = \tex_copy:D #1
+    \box_ht:N #1 \@@_dim_eval:n {#2}
+  }
+\cs_generate_variant:Nn \box_set_ht:Nn { c }
+\cs_new_protected:Npn \box_gset_ht:Nn #1#2
+  { \box_ht:N #1 \@@_dim_eval:n {#2} }
+\cs_generate_variant:Nn \box_gset_ht:Nn { c }
+\cs_new_protected:Npn \box_set_wd:Nn #1#2
+  {
+    \tex_setbox:D #1 = \tex_copy:D #1
+    \box_wd:N #1 \@@_dim_eval:n {#2}
+  }
+\cs_generate_variant:Nn \box_set_wd:Nn { c }
+\cs_new_protected:Npn \box_gset_wd:Nn #1#2
+  { \box_wd:N #1 \@@_dim_eval:n {#2} }
+\cs_generate_variant:Nn \box_gset_wd:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Using boxes}
+%
+% \begin{macro}{\box_use_drop:N, \box_use_drop:c}
+% \begin{macro}{\box_use:N, \box_use:c}
+%   Using a \meta{box}. These are just \TeX{} primitives with meaningful
+%   names.
+%    \begin{macrocode}
+\cs_new_eq:NN \box_use_drop:N \tex_box:D
+\cs_new_eq:NN \box_use:N \tex_copy:D
+\cs_generate_variant:Nn \box_use_drop:N { c }
+\cs_generate_variant:Nn \box_use:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\box_move_left:nn, \box_move_right:nn}
+% \begin{macro}{\box_move_up:nn, \box_move_down:nn}
+% \testfile*
+%   Move box material in different directions.
+%   When debugging, the dimension expression |#1| is surrounded by
+%   parentheses to catch early termination.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_move_left:nn #1#2
+  { \tex_moveleft:D \@@_dim_eval:n {#1} #2 }
+\cs_new_protected:Npn \box_move_right:nn #1#2
+  { \tex_moveright:D \@@_dim_eval:n {#1} #2 }
+\cs_new_protected:Npn \box_move_up:nn #1#2
+  { \tex_raise:D \@@_dim_eval:n {#1} #2 }
+\cs_new_protected:Npn \box_move_down:nn #1#2
+  { \tex_lower:D \@@_dim_eval:n {#1} #2 }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Box conditionals}
+%
+% \begin{macro}{\if_hbox:N}
+% \begin{macro}{\if_vbox:N}
+% \begin{macro}{\if_box_empty:N}
+%  \testfile*
+%    The primitives for testing if a \meta{box} is empty/void or which
+%    type of box it is.
+%    \begin{macrocode}
+\cs_new_eq:NN \if_hbox:N      \tex_ifhbox:D
+\cs_new_eq:NN \if_vbox:N      \tex_ifvbox:D
+\cs_new_eq:NN \if_box_empty:N \tex_ifvoid:D
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\box_if_horizontal:N, \box_if_horizontal:c}
+% \testfile*
+% \begin{macro}[pTF]{\box_if_vertical:N, \box_if_vertical:c}
+% \testfile*
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \box_if_horizontal:N #1 { p , T , F , TF }
+  { \if_hbox:N #1 \prg_return_true: \else: \prg_return_false: \fi: }
+\prg_new_conditional:Npnn \box_if_vertical:N #1 { p , T , F , TF }
+  { \if_vbox:N #1 \prg_return_true: \else: \prg_return_false: \fi: }
+\prg_generate_conditional_variant:Nnn \box_if_horizontal:N
+  { c } { p , T , F , TF }
+\prg_generate_conditional_variant:Nnn \box_if_vertical:N
+  { c } { p , T , F , TF }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\box_if_empty:N, \box_if_empty:c}
+% \testfile*
+%   Testing if a \meta{box} is empty/void.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \box_if_empty:N #1 { p , T , F , TF }
+  { \if_box_empty:N #1 \prg_return_true: \else: \prg_return_false: \fi: }
+\prg_generate_conditional_variant:Nnn \box_if_empty:N
+  { c } { p , T , F , TF }
+%    \end{macrocode}
+%  \end{macro}
+%  \end{macro}
+%
+% \subsection{The last box inserted}
+%
+% \begin{macro}{\box_set_to_last:N, \box_set_to_last:c}
+% \begin{macro}{\box_gset_to_last:N, \box_gset_to_last:c}
+% \testfile*
+%    Set a box to the previous box.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_set_to_last:N #1
+  { \tex_setbox:D #1 \tex_lastbox:D }
+\cs_new_protected:Npn \box_gset_to_last:N #1
+  { \tex_global:D \tex_setbox:D #1 \tex_lastbox:D }
+\cs_generate_variant:Nn \box_set_to_last:N  { c }
+\cs_generate_variant:Nn \box_gset_to_last:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Constant boxes}
+%
+% \begin{variable}{\c_empty_box}
+%  A box we never use.
+%    \begin{macrocode}
+\box_new:N \c_empty_box
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Scratch boxes}
+%
+%  \begin{variable}{\l_tmpa_box, \l_tmpb_box, \g_tmpa_box, \g_tmpb_box}
+%    Scratch boxes.
+%    \begin{macrocode}
+\box_new:N \l_tmpa_box
+\box_new:N \l_tmpb_box
+\box_new:N \g_tmpa_box
+\box_new:N \g_tmpb_box
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Viewing box contents}
+%
+% \TeX{}'s \tn{showbox} is not really that helpful in many cases, and
+% it is also inconsistent with other \LaTeX3{} \texttt{show} functions as it
+% does not actually shows material in the terminal. So we provide a richer
+% set of functionality.
+%
+% \begin{macro}{\box_show:N, \box_show:c}
+% \begin{macro}{\box_show:Nnn, \box_show:cnn}
+%   Essentially a wrapper around the internal function, but evaluating
+%   the breadth and depth arguments now outside the group.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_show:N #1
+  { \box_show:Nnn #1 \c_max_int \c_max_int }
+\cs_generate_variant:Nn \box_show:N { c }
+\cs_new_protected:Npn \box_show:Nnn #1#2#3
+  { \@@_show:NNff 1 #1 { \int_eval:n {#2} } { \int_eval:n {#3} } }
+\cs_generate_variant:Nn \box_show:Nnn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\box_log:N, \box_log:c}
+% \begin{macro}{\box_log:Nnn, \box_log:cnn}
+% \begin{macro}{\@@_log:nNnn}
+%   Getting \TeX{} to write to the log without interruption the run is done by
+%   altering the interaction mode. For that, the \eTeX{} extensions are needed.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_log:N #1
+  { \box_log:Nnn #1 \c_max_int \c_max_int }
+\cs_generate_variant:Nn \box_log:N { c }
+\cs_new_protected:Npn \box_log:Nnn
+  { \exp_args:No \@@_log:nNnn { \tex_the:D \tex_interactionmode:D } }
+\cs_new_protected:Npn \@@_log:nNnn #1#2#3#4
+  {
+    \int_gset:Nn \tex_interactionmode:D { 0 }
+    \@@_show:NNff 0 #2 { \int_eval:n {#3} } { \int_eval:n {#4} }
+    \int_gset:Nn \tex_interactionmode:D {#1}
+  }
+\cs_generate_variant:Nn \box_log:Nnn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_show:NNnn, \@@_show:NNff}
+%   The internal auxiliary to actually do the output uses a group to deal
+%   with breadth and depth values. The \cs{use:n} here gives better output
+%   appearance. Setting \tn{tracingonline} and \tn{errorcontextlines} is
+%   used to control what appears in the terminal.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_show:NNnn #1#2#3#4
+  {
+    \box_if_exist:NTF #2
+      {
+        \group_begin:
+          \int_set:Nn \tex_showboxbreadth:D {#3}
+          \int_set:Nn \tex_showboxdepth:D   {#4}
+          \int_set:Nn \tex_tracingonline:D  {#1}
+          \int_set:Nn \tex_errorcontextlines:D { -1 }
+          \tex_showbox:D \use:n {#2}
+        \group_end:
+      }
+      {
+        \msg_error:nne { kernel } { variable-not-defined }
+          { \token_to_str:N #2 }
+      }
+  }
+\cs_generate_variant:Nn \@@_show:NNnn { NNff }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Horizontal mode boxes}
+%
+% \begin{macro}{\hbox:n}
+% \testfile{m3box002.lvt}
+%   Put a horizontal box directly into the input stream.
+%    \begin{macrocode}
+\cs_new_protected:Npn \hbox:n #1
+  { \tex_hbox:D \scan_stop: { \color_group_begin: #1 \color_group_end: } }
+%    \end{macrocode}
+%  \end{macro}
+%
+% \begin{macro}{\hbox_set:Nn, \hbox_set:cn}
+% \begin{macro}{\hbox_gset:Nn, \hbox_gset:cn}
+% \testfile*
+%    \begin{macrocode}
+\cs_new_protected:Npn \hbox_set:Nn #1#2
+  {
+    \tex_setbox:D #1 \tex_hbox:D
+      { \color_group_begin: #2 \color_group_end: }
+  }
+\cs_new_protected:Npn \hbox_gset:Nn #1#2
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_hbox:D
+      { \color_group_begin: #2 \color_group_end: }
+  }
+\cs_generate_variant:Nn \hbox_set:Nn { c }
+\cs_generate_variant:Nn \hbox_gset:Nn { c }
+%    \end{macrocode}
+%  \end{macro}
+%  \end{macro}
+%
+% \begin{macro}{\hbox_set_to_wd:Nnn, \hbox_set_to_wd:cnn}
+% \begin{macro}{\hbox_gset_to_wd:Nnn, \hbox_gset_to_wd:cnn}
+% \testfile*
+%   Storing material in a horizontal box with a specified width.
+%   Again, put the dimension expression in parentheses when debugging.
+%    \begin{macrocode}
+\cs_new_protected:Npn \hbox_set_to_wd:Nnn #1#2#3
+  {
+    \tex_setbox:D #1 \tex_hbox:D to \@@_dim_eval:n {#2}
+      { \color_group_begin: #3 \color_group_end: }
+  }
+\cs_new_protected:Npn \hbox_gset_to_wd:Nnn #1#2#3
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_hbox:D to \@@_dim_eval:n {#2}
+      { \color_group_begin: #3 \color_group_end: }
+  }
+\cs_generate_variant:Nn \hbox_set_to_wd:Nnn { c }
+\cs_generate_variant:Nn \hbox_gset_to_wd:Nnn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hbox_set:Nw, \hbox_set:cw}
+% \begin{macro}{\hbox_gset:Nw, \hbox_gset:cw}
+% \begin{macro}{\hbox_set_end:, \hbox_gset_end:}
+% \testfile*
+%    Storing material in a horizontal box. This type is useful in
+%    environment definitions.
+%    \begin{macrocode}
+\cs_new_protected:Npn \hbox_set:Nw  #1
+  {
+    \tex_setbox:D #1 \tex_hbox:D
+      \c_group_begin_token
+        \color_group_begin:
+  }
+\cs_new_protected:Npn \hbox_gset:Nw  #1
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_hbox:D
+      \c_group_begin_token
+        \color_group_begin:
+  }
+\cs_generate_variant:Nn \hbox_set:Nw  { c }
+\cs_generate_variant:Nn \hbox_gset:Nw { c }
+\cs_new_protected:Npn \hbox_set_end:
+  {
+      \color_group_end:
+    \c_group_end_token
+  }
+\cs_new_eq:NN \hbox_gset_end: \hbox_set_end:
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hbox_set_to_wd:Nnw, \hbox_set_to_wd:cnw}
+% \begin{macro}{\hbox_gset_to_wd:Nnw, \hbox_gset_to_wd:cnw}
+%   Combining the above ideas.
+%    \begin{macrocode}
+\cs_new_protected:Npn \hbox_set_to_wd:Nnw #1#2
+  {
+    \tex_setbox:D #1 \tex_hbox:D to \@@_dim_eval:n {#2}
+      \c_group_begin_token
+        \color_group_begin:
+  }
+\cs_new_protected:Npn \hbox_gset_to_wd:Nnw #1#2
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_hbox:D to \@@_dim_eval:n {#2}
+      \c_group_begin_token
+        \color_group_begin:
+  }
+\cs_generate_variant:Nn \hbox_set_to_wd:Nnw  { c }
+\cs_generate_variant:Nn \hbox_gset_to_wd:Nnw { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%  \begin{macro}{\hbox_to_wd:nn}
+%  \begin{macro}{\hbox_to_zero:n}
+%  \testfile*
+%   Put a horizontal box directly into the input stream.
+%    \begin{macrocode}
+\cs_new_protected:Npn \hbox_to_wd:nn #1#2
+  {
+    \tex_hbox:D to \@@_dim_eval:n {#1}
+      { \color_group_begin: #2 \color_group_end: }
+  }
+\cs_new_protected:Npn \hbox_to_zero:n #1
+  {
+    \tex_hbox:D to \c_zero_dim
+      { \color_group_begin: #1 \color_group_end: }
+  }
+%    \end{macrocode}
+%  \end{macro}
+%  \end{macro}
+%
+% \begin{macro}{\hbox_overlap_center:n, \hbox_overlap_left:n, \hbox_overlap_right:n}
+%   Put a zero-sized box with the contents pushed against one side (which
+%   makes it stick out on the other) directly into the input stream.
+%    \begin{macrocode}
+\cs_new_protected:Npn \hbox_overlap_center:n  #1
+  { \hbox_to_zero:n { \tex_hss:D #1 \tex_hss:D } }
+\cs_new_protected:Npn \hbox_overlap_left:n  #1
+  { \hbox_to_zero:n { \tex_hss:D #1 } }
+\cs_new_protected:Npn \hbox_overlap_right:n #1
+  { \hbox_to_zero:n { #1 \tex_hss:D } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hbox_unpack:N, \hbox_unpack:c}
+% \begin{macro}{\hbox_unpack_drop:N, \hbox_unpack_drop:c}
+% \testfile*
+%   Unpacking a box and if requested also clear it.
+%    \begin{macrocode}
+\cs_new_eq:NN \hbox_unpack:N \tex_unhcopy:D
+\cs_new_eq:NN \hbox_unpack_drop:N \tex_unhbox:D
+\cs_generate_variant:Nn \hbox_unpack:N { c }
+\cs_generate_variant:Nn \hbox_unpack_drop:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Vertical mode boxes}
+%
+% \TeX{} ends these boxes directly with the internal \emph{end_graf}
+% routine. This means that there is no \cs{par} at the end of vertical
+% boxes unless we insert one. Thus all vertical boxes include a \cs{par}
+% just before closing the color group.
+%
+% \begin{macro}{\vbox:n}
+% \TestFiles{m3box003.lvt}
+% \begin{macro}{\vbox_top:n}
+% \TestFiles{m3box003.lvt}
+%   Put a vertical box directly into the input stream.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vbox:n #1
+  { \tex_vbox:D { \color_group_begin: #1 \par \color_group_end: } }
+\cs_new_protected:Npn \vbox_top:n #1
+  { \tex_vtop:D { \color_group_begin: #1 \par \color_group_end: } }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\vbox_to_ht:nn, \vbox_to_zero:n}
+% \begin{macro}{\vbox_to_ht:nn, \vbox_to_zero:n}
+% \testfile*
+%   Put a vertical box directly into the input stream.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vbox_to_ht:nn #1#2
+  {
+    \tex_vbox:D to \@@_dim_eval:n {#1}
+      { \color_group_begin: #2 \par \color_group_end: }
+  }
+\cs_new_protected:Npn \vbox_to_zero:n #1
+  {
+    \tex_vbox:D to \c_zero_dim
+      { \color_group_begin: #1 \par \color_group_end: }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\vbox_set:Nn, \vbox_set:cn}
+% \begin{macro}{\vbox_gset:Nn, \vbox_gset:cn}
+% \testfile*
+%   Storing material in a vertical box with a natural height.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vbox_set:Nn #1#2
+  {
+    \tex_setbox:D #1 \tex_vbox:D
+      { \color_group_begin: #2 \par \color_group_end: }
+  }
+\cs_new_protected:Npn \vbox_gset:Nn #1#2
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_vbox:D
+      { \color_group_begin: #2 \par \color_group_end: }
+  }
+\cs_generate_variant:Nn \vbox_set:Nn  { c }
+\cs_generate_variant:Nn \vbox_gset:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\vbox_set_top:Nn, \vbox_set_top:cn}
+% \begin{macro}{\vbox_gset_top:Nn, \vbox_gset_top:cn}
+% \testfile*
+%   Storing material in a vertical box with a natural height and reference
+%   point at the baseline of the first object in the box.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vbox_set_top:Nn #1#2
+  {
+    \tex_setbox:D #1 \tex_vtop:D
+      { \color_group_begin: #2 \par \color_group_end: }
+  }
+\cs_new_protected:Npn \vbox_gset_top:Nn #1#2
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_vtop:D
+      { \color_group_begin: #2 \par \color_group_end: }
+  }
+\cs_generate_variant:Nn \vbox_set_top:Nn { c }
+\cs_generate_variant:Nn \vbox_gset_top:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\vbox_set_to_ht:Nnn, \vbox_set_to_ht:cnn}
+% \begin{macro}{\vbox_gset_to_ht:Nnn, \vbox_gset_to_ht:cnn}
+%  \testfile*
+%  Storing material in a vertical box with a specified height.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vbox_set_to_ht:Nnn #1#2#3
+  {
+    \tex_setbox:D #1 \tex_vbox:D to \@@_dim_eval:n {#2}
+      { \color_group_begin: #3 \par \color_group_end: }
+  }
+\cs_new_protected:Npn \vbox_gset_to_ht:Nnn #1#2#3
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_vbox:D to \@@_dim_eval:n {#2}
+      { \color_group_begin: #3 \par \color_group_end: }
+  }
+\cs_generate_variant:Nn \vbox_set_to_ht:Nnn  { c }
+\cs_generate_variant:Nn \vbox_gset_to_ht:Nnn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\vbox_set:Nw, \vbox_set:cw}
+% \begin{macro}{\vbox_gset:Nw, \vbox_gset:cw}
+% \begin{macro}{\vbox_set_end:, \vbox_gset_end:}
+% \testfile*
+%   Storing material in a vertical box. This type is useful in
+%   environment definitions.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vbox_set:Nw #1
+  {
+    \tex_setbox:D #1 \tex_vbox:D
+      \c_group_begin_token
+        \color_group_begin:
+  }
+\cs_new_protected:Npn \vbox_gset:Nw #1
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_vbox:D
+      \c_group_begin_token
+        \color_group_begin:
+  }
+\cs_generate_variant:Nn \vbox_set:Nw  { c }
+\cs_generate_variant:Nn \vbox_gset:Nw { c }
+\cs_new_protected:Npn \vbox_set_end:
+  {
+        \par
+      \color_group_end:
+    \c_group_end_token
+  }
+\cs_new_eq:NN \vbox_gset_end: \vbox_set_end:
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\vbox_set_to_ht:Nnw, \vbox_set_to_ht:cnw}
+% \begin{macro}{\vbox_gset_to_ht:Nnw, \vbox_gset_to_ht:cnw}
+%   A combination of the above ideas.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vbox_set_to_ht:Nnw #1#2
+  {
+    \tex_setbox:D #1 \tex_vbox:D to \@@_dim_eval:n {#2}
+      \c_group_begin_token
+        \color_group_begin:
+  }
+\cs_new_protected:Npn \vbox_gset_to_ht:Nnw #1#2
+  {
+    \tex_global:D \tex_setbox:D #1 \tex_vbox:D to \@@_dim_eval:n {#2}
+      \c_group_begin_token
+        \color_group_begin:
+  }
+\cs_generate_variant:Nn \vbox_set_to_ht:Nnw  { c }
+\cs_generate_variant:Nn \vbox_gset_to_ht:Nnw { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\vbox_unpack:N, \vbox_unpack:c}
+% \begin{macro}{\vbox_unpack_drop:N, \vbox_unpack_drop:c}
+% \testfile*
+%   Unpacking a box and if requested also clear it.
+%    \begin{macrocode}
+\cs_new_eq:NN \vbox_unpack:N \tex_unvcopy:D
+\cs_new_eq:NN \vbox_unpack_drop:N \tex_unvbox:D
+\cs_generate_variant:Nn \vbox_unpack:N { c }
+\cs_generate_variant:Nn \vbox_unpack_drop:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \vbox_set_split_to_ht:NNn, \vbox_set_split_to_ht:cNn,
+%     \vbox_set_split_to_ht:Ncn, \vbox_set_split_to_ht:ccn,
+%     \vbox_gset_split_to_ht:NNn, \vbox_gset_split_to_ht:cNn,
+%     \vbox_gset_split_to_ht:Ncn, \vbox_gset_split_to_ht:ccn,
+%   }
+% \testfile*
+%   Splitting a vertical box in two.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vbox_set_split_to_ht:NNn #1#2#3
+  { \tex_setbox:D #1 \tex_vsplit:D #2 to \@@_dim_eval:n {#3} }
+\cs_generate_variant:Nn \vbox_set_split_to_ht:NNn { c , Nc , cc }
+\cs_new_protected:Npn \vbox_gset_split_to_ht:NNn #1#2#3
+  {
+    \tex_global:D \tex_setbox:D #1
+      \tex_vsplit:D #2 to \@@_dim_eval:n {#3}
+  }
+\cs_generate_variant:Nn \vbox_gset_split_to_ht:NNn { c , Nc , cc }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Affine transformations}
+%
+% \begin{variable}{\l_@@_angle_fp}
+%   When rotating boxes, the angle itself may be needed by the
+%   engine-dependent code. This is done using the \pkg{fp} module so
+%   that the value is tidied up properly.
+%    \begin{macrocode}
+\fp_new:N \l_@@_angle_fp
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_cos_fp, \l_@@_sin_fp}
+%   These are used to hold the calculated sine and cosine values while
+%   carrying out a rotation.
+%    \begin{macrocode}
+\fp_new:N \l_@@_cos_fp
+\fp_new:N \l_@@_sin_fp
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {\l_@@_top_dim, \l_@@_bottom_dim, \l_@@_left_dim, \l_@@_right_dim}
+%   These are the positions of the four edges of a box before
+%   manipulation.
+%    \begin{macrocode}
+\dim_new:N \l_@@_top_dim
+\dim_new:N \l_@@_bottom_dim
+\dim_new:N \l_@@_left_dim
+\dim_new:N \l_@@_right_dim
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%  {
+%    \l_@@_top_new_dim,  \l_@@_bottom_new_dim ,
+%    \l_@@_left_new_dim, \l_@@_right_new_dim
+%  }
+%   These are the positions of the four edges of a box after
+%   manipulation.
+%    \begin{macrocode}
+\dim_new:N \l_@@_top_new_dim
+\dim_new:N \l_@@_bottom_new_dim
+\dim_new:N \l_@@_left_new_dim
+\dim_new:N \l_@@_right_new_dim
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_internal_box}
+%   Scratch space, but also needed by some parts of the driver.
+%    \begin{macrocode}
+\box_new:N \l_@@_internal_box
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+%   {
+%     \box_rotate:Nn, \box_rotate:cn,
+%     \box_grotate:Nn, \box_grotate:cn
+%   }
+% \begin{macro}{\@@_rotate:NnN}
+% \begin{macro}{\@@_rotate:N}
+% \begin{macro}{\@@_rotate_xdir:nnN, \@@_rotate_ydir:nnN}
+% \begin{macro}
+%   {
+%     \@@_rotate_quadrant_one:,   \@@_rotate_quadrant_two:,
+%     \@@_rotate_quadrant_three:, \@@_rotate_quadrant_four:
+%   }
+%   Rotation of a box starts with working out the relevant sine and
+%   cosine. The actual rotation is in an auxiliary to keep the flow slightly
+%   clearer
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_rotate:Nn #1#2
+  { \@@_rotate:NnN #1 {#2} \hbox_set:Nn }
+\cs_generate_variant:Nn \box_rotate:Nn { c }
+\cs_new_protected:Npn \box_grotate:Nn #1#2
+  { \@@_rotate:NnN #1 {#2} \hbox_gset:Nn }
+\cs_generate_variant:Nn \box_grotate:Nn { c }
+\cs_new_protected:Npn \@@_rotate:NnN #1#2#3
+  {
+    #3 #1
+      {
+        \fp_set:Nn \l_@@_angle_fp {#2}
+        \fp_set:Nn \l_@@_sin_fp { sind ( \l_@@_angle_fp ) }
+        \fp_set:Nn \l_@@_cos_fp { cosd ( \l_@@_angle_fp ) }
+        \@@_rotate:N #1
+      }
+  }
+%    \end{macrocode}
+%   The edges of the box are then recorded: the left edge is
+%   always at zero. Rotation of the four edges then takes place: this is
+%   most efficiently done on a quadrant by quadrant basis.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate:N #1
+  {
+    \dim_set:Nn \l_@@_top_dim    {  \box_ht:N #1 }
+    \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
+    \dim_set:Nn \l_@@_right_dim  {  \box_wd:N #1 }
+    \dim_zero:N \l_@@_left_dim
+%    \end{macrocode}
+%   The next step is to work out the $x$ and $y$ coordinates of vertices of
+%   the rotated box in relation to its original coordinates. The box can be
+%   visualized with vertices $B$, $C$, $D$ and $E$ is illustrated
+%   (Figure~\ref{fig:l3box:rotation}). The vertex $O$ is the reference point
+%   on the baseline, and in this implementation is also the centre of rotation.
+%   \begin{figure}
+%     \centering
+%     \setlength{\unitlength}{3pt}^^A
+%     \begin{picture}(34,36)(12,44)
+%       \thicklines
+%       \put(20,52){\dashbox{1}(20,21){}}
+%       \put(20,80){\line(0,-1){36}}
+%       \put(12,58){\line(1, 0){34}}
+%       \put(41,59){A}
+%       \put(40,74){B}
+%       \put(21,74){C}
+%       \put(21,49){D}
+%       \put(40,49){E}
+%       \put(21,59){O}
+%     \end{picture}
+%     \caption{Co-ordinates of a box prior to rotation.}
+%     \label{fig:l3box:rotation}
+%   \end{figure}
+%   The formulae are, for a point $P$ and angle $\alpha$:
+%   \[
+%     \begin{array}{l}
+%       P'_x = P_x - O_x \\
+%       P'_y = P_y - O_y \\
+%       P''_x =  ( P'_x \cos(\alpha)) - ( P'_y \sin(\alpha) ) \\
+%       P''_y =  ( P'_x \sin(\alpha)) + ( P'_y \cos(\alpha) ) \\
+%       P'''_x = P''_x + O_x + L_x \\
+%       P'''_y = P''_y + O_y
+%    \end{array}
+%   \]
+%   The \enquote{extra} horizontal translation $L_x$ at the end is calculated
+%   so that the leftmost point of the resulting box has $x$-coordinate $0$.
+%   This is desirable as \TeX{} boxes must have the reference point at
+%   the left edge of the box. (As $O$ is always $(0,0)$, this part of the
+%   calculation is omitted here.)
+%    \begin{macrocode}
+    \fp_compare:nNnTF \l_@@_sin_fp > \c_zero_fp
+      {
+        \fp_compare:nNnTF \l_@@_cos_fp > \c_zero_fp
+          { \@@_rotate_quadrant_one: }
+          { \@@_rotate_quadrant_two: }
+      }
+      {
+        \fp_compare:nNnTF \l_@@_cos_fp < \c_zero_fp
+          { \@@_rotate_quadrant_three: }
+          { \@@_rotate_quadrant_four: }
+      }
+%    \end{macrocode}
+%   The position of the box edges are now known, but the box at this
+%   stage be misplaced relative to the current \TeX{} reference point. So the
+%   content of the box is moved such that the reference point of the
+%   rotated box is in the same place as the original.
+%    \begin{macrocode}
+    \hbox_set:Nn \l_@@_internal_box { \box_use:N #1 }
+    \hbox_set:Nn \l_@@_internal_box
+      {
+        \__kernel_kern:n { -\l_@@_left_new_dim }
+        \hbox:n
+          {
+            \@@_backend_rotate:Nn
+              \l_@@_internal_box
+              \l_@@_angle_fp
+          }
+      }
+%    \end{macrocode}
+%   Tidy up the size of the box so that the material is actually inside
+%   the bounding box. The result can then be used to reset the original
+%   box.
+%    \begin{macrocode}
+    \box_set_ht:Nn \l_@@_internal_box {  \l_@@_top_new_dim }
+    \box_set_dp:Nn \l_@@_internal_box { -\l_@@_bottom_new_dim }
+    \box_set_wd:Nn \l_@@_internal_box
+      { \l_@@_right_new_dim - \l_@@_left_new_dim }
+    \box_use_drop:N \l_@@_internal_box
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%   These functions take a general point $(|#1|, |#2|)$ and rotate its
+%   location about the origin, using the previously-set sine and cosine
+%   values. Each function gives only one component of the location of the
+%   updated point. This is because for rotation of a box each step needs
+%   only one value, and so performance is gained by avoiding working
+%   out both $x'$ and $y'$ at the same time. Contrast this with
+%   the equivalent function in the \pkg{l3coffins} module, where both parts
+%   are needed.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_xdir:nnN #1#2#3
+  {
+    \dim_set:Nn #3
+      {
+        \fp_to_dim:n
+          {
+              \l_@@_cos_fp * \dim_to_fp:n {#1}
+            - \l_@@_sin_fp * \dim_to_fp:n {#2}
+          }
+      }
+  }
+\cs_new_protected:Npn \@@_rotate_ydir:nnN #1#2#3
+  {
+    \dim_set:Nn #3
+      {
+        \fp_to_dim:n
+          {
+              \l_@@_sin_fp * \dim_to_fp:n {#1}
+            + \l_@@_cos_fp * \dim_to_fp:n {#2}
+          }
+      }
+  }
+%    \end{macrocode}
+%   Rotation of the edges is done using a different formula for each
+%   quadrant. In every case, the top and bottom edges only need the
+%   resulting $y$-values, whereas the left and right edges need the
+%   $x$-values. Each case is a question of picking out which corner
+%   ends up at with the maximum top, bottom, left and right value. Doing
+%   this by hand means a lot less calculating and avoids lots of
+%   comparisons.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_quadrant_one:
+  {
+    \@@_rotate_ydir:nnN \l_@@_right_dim \l_@@_top_dim
+      \l_@@_top_new_dim
+    \@@_rotate_ydir:nnN \l_@@_left_dim  \l_@@_bottom_dim
+      \l_@@_bottom_new_dim
+    \@@_rotate_xdir:nnN \l_@@_left_dim  \l_@@_top_dim
+      \l_@@_left_new_dim
+    \@@_rotate_xdir:nnN \l_@@_right_dim \l_@@_bottom_dim
+      \l_@@_right_new_dim
+  }
+\cs_new_protected:Npn \@@_rotate_quadrant_two:
+  {
+    \@@_rotate_ydir:nnN \l_@@_right_dim \l_@@_bottom_dim
+      \l_@@_top_new_dim
+    \@@_rotate_ydir:nnN \l_@@_left_dim  \l_@@_top_dim
+      \l_@@_bottom_new_dim
+    \@@_rotate_xdir:nnN \l_@@_right_dim  \l_@@_top_dim
+      \l_@@_left_new_dim
+    \@@_rotate_xdir:nnN \l_@@_left_dim   \l_@@_bottom_dim
+      \l_@@_right_new_dim
+  }
+\cs_new_protected:Npn \@@_rotate_quadrant_three:
+  {
+    \@@_rotate_ydir:nnN \l_@@_left_dim  \l_@@_bottom_dim
+      \l_@@_top_new_dim
+    \@@_rotate_ydir:nnN \l_@@_right_dim \l_@@_top_dim
+      \l_@@_bottom_new_dim
+    \@@_rotate_xdir:nnN \l_@@_right_dim \l_@@_bottom_dim
+      \l_@@_left_new_dim
+    \@@_rotate_xdir:nnN \l_@@_left_dim   \l_@@_top_dim
+      \l_@@_right_new_dim
+  }
+\cs_new_protected:Npn \@@_rotate_quadrant_four:
+  {
+    \@@_rotate_ydir:nnN \l_@@_left_dim  \l_@@_top_dim
+      \l_@@_top_new_dim
+    \@@_rotate_ydir:nnN \l_@@_right_dim \l_@@_bottom_dim
+      \l_@@_bottom_new_dim
+    \@@_rotate_xdir:nnN \l_@@_left_dim  \l_@@_bottom_dim
+      \l_@@_left_new_dim
+    \@@_rotate_xdir:nnN \l_@@_right_dim \l_@@_top_dim
+      \l_@@_right_new_dim
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_scale_x_fp, \l_@@_scale_y_fp}
+%   Scaling is potentially-different in the two axes.
+%    \begin{macrocode}
+\fp_new:N \l_@@_scale_x_fp
+\fp_new:N \l_@@_scale_y_fp
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+%   {
+%     \box_resize_to_wd_and_ht_plus_dp:Nnn,
+%     \box_resize_to_wd_and_ht_plus_dp:cnn,
+%     \box_gresize_to_wd_and_ht_plus_dp:Nnn,
+%     \box_gresize_to_wd_and_ht_plus_dp:cnn
+%   }
+% \begin{macro}{\@@_resize_to_wd_and_ht_plus_dp:NnnN}
+% \begin{macro}{\@@_resize_set_corners:N}
+% \begin{macro}{\@@_resize:N}
+% \begin{macro}{\@@_resize:NNN}
+%   Resizing a box starts by working out the various dimensions of the
+%   existing box.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_resize_to_wd_and_ht_plus_dp:Nnn #1#2#3
+  {
+    \@@_resize_to_wd_and_ht_plus_dp:NnnN #1 {#2} {#3}
+      \hbox_set:Nn
+  }
+\cs_generate_variant:Nn \box_resize_to_wd_and_ht_plus_dp:Nnn { c }
+\cs_new_protected:Npn \box_gresize_to_wd_and_ht_plus_dp:Nnn #1#2#3
+  {
+    \@@_resize_to_wd_and_ht_plus_dp:NnnN #1 {#2} {#3}
+      \hbox_gset:Nn
+  }
+\cs_generate_variant:Nn \box_gresize_to_wd_and_ht_plus_dp:Nnn { c }
+\cs_new_protected:Npn \@@_resize_to_wd_and_ht_plus_dp:NnnN #1#2#3#4
+  {
+    #4 #1
+      {
+        \@@_resize_set_corners:N #1
+%    \end{macrocode}
+%   The $x$-scaling and resulting box size is easy enough to work
+%   out: the dimension is that given as |#2|, and the scale is simply the
+%   new width divided by the old one.
+%    \begin{macrocode}
+        \fp_set:Nn \l_@@_scale_x_fp
+          { \dim_to_fp:n {#2} / \dim_to_fp:n { \l_@@_right_dim } }
+%    \end{macrocode}
+%   The $y$-scaling needs both the height and the depth of the current box.
+%    \begin{macrocode}
+        \fp_set:Nn \l_@@_scale_y_fp
+          {
+              \dim_to_fp:n {#3}
+            / \dim_to_fp:n { \l_@@_top_dim - \l_@@_bottom_dim }
+          }
+%    \end{macrocode}
+%   Hand off to the auxiliary which does the rest of the work.
+%    \begin{macrocode}
+        \@@_resize:N #1
+      }
+  }
+\cs_new_protected:Npn \@@_resize_set_corners:N #1
+  {
+    \dim_set:Nn \l_@@_top_dim    {  \box_ht:N #1 }
+    \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
+    \dim_set:Nn \l_@@_right_dim  {  \box_wd:N #1 }
+    \dim_zero:N \l_@@_left_dim
+  }
+%    \end{macrocode}
+%   With at least one real scaling to do, the next phase is to find the new
+%   edge co-ordinates. In the $x$~direction this is relatively easy: just
+%   scale the right edge. In the $y$~direction, both dimensions have to be
+%   scaled, and this again needs the absolute scale value.
+%   Once that is all done, the common resize/rescale code can be employed.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_resize:N #1
+  {
+    \@@_resize:NNN \l_@@_right_new_dim
+      \l_@@_scale_x_fp \l_@@_right_dim
+    \@@_resize:NNN \l_@@_bottom_new_dim
+      \l_@@_scale_y_fp \l_@@_bottom_dim
+    \@@_resize:NNN \l_@@_top_new_dim
+      \l_@@_scale_y_fp \l_@@_top_dim
+    \@@_resize_common:N #1
+  }
+\cs_new_protected:Npn \@@_resize:NNN #1#2#3
+  {
+    \dim_set:Nn #1
+      { \fp_to_dim:n { \fp_abs:n { #2 } * \dim_to_fp:n { #3 } } }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \box_resize_to_ht:Nn, \box_resize_to_ht:cn,
+%     \box_gresize_to_ht:Nn, \box_gresize_to_ht:cn
+%   }
+% \begin{macro}{\@@_resize_to_ht:NnN}
+% \begin{macro}
+%   {
+%     \box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn,
+%     \box_gresize_to_ht_plus_dp:Nn, \box_gresize_to_ht_plus_dp:cn
+%   }
+% \begin{macro}{\@@_resize_to_ht_plus_dp:NnN}
+% \begin{macro}
+%   {
+%     \box_resize_to_wd:Nn, \box_resize_to_wd:cn,
+%     \box_gresize_to_wd:Nn, \box_gresize_to_wd:cn
+%   }
+% \begin{macro}{\@@_resize_to_wd:NnN}
+% \begin{macro}
+%   {
+%     \box_resize_to_wd_and_ht:Nnn, \box_resize_to_wd_and_ht:cnn,
+%     \box_gresize_to_wd_and_ht:Nnn, \box_gresize_to_wd_and_ht:cnn
+%   }
+% \begin{macro}{\@@_resize_to_wd_ht:NnnN}
+%   Scaling to a (total) height or to a width is a simplified version of the main
+%   resizing operation, with the scale simply copied between the two parts. The
+%   internal auxiliary is called using the scaling value twice, as the sign for
+%   both parts is needed (as this allows the same internal code to be used as
+%   for the general case).
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_resize_to_ht:Nn #1#2
+  { \@@_resize_to_ht:NnN #1 {#2} \hbox_set:Nn }
+\cs_generate_variant:Nn \box_resize_to_ht:Nn { c }
+\cs_new_protected:Npn \box_gresize_to_ht:Nn #1#2
+  { \@@_resize_to_ht:NnN #1 {#2} \hbox_gset:Nn }
+\cs_generate_variant:Nn \box_gresize_to_ht:Nn { c }
+\cs_new_protected:Npn \@@_resize_to_ht:NnN #1#2#3
+  {
+    #3 #1
+      {
+        \@@_resize_set_corners:N #1
+        \fp_set:Nn \l_@@_scale_y_fp
+          {
+              \dim_to_fp:n {#2}
+            / \dim_to_fp:n { \l_@@_top_dim }
+          }
+        \fp_set_eq:NN \l_@@_scale_x_fp \l_@@_scale_y_fp
+        \@@_resize:N #1
+      }
+  }
+\cs_new_protected:Npn \box_resize_to_ht_plus_dp:Nn #1#2
+  { \@@_resize_to_ht_plus_dp:NnN #1 {#2} \hbox_set:Nn }
+\cs_generate_variant:Nn \box_resize_to_ht_plus_dp:Nn { c }
+\cs_new_protected:Npn \box_gresize_to_ht_plus_dp:Nn #1#2
+  { \@@_resize_to_ht_plus_dp:NnN #1 {#2} \hbox_gset:Nn }
+\cs_generate_variant:Nn \box_gresize_to_ht_plus_dp:Nn { c }
+\cs_new_protected:Npn \@@_resize_to_ht_plus_dp:NnN #1#2#3
+  {
+    #3 #1
+      {
+        \@@_resize_set_corners:N #1
+        \fp_set:Nn \l_@@_scale_y_fp
+          {
+              \dim_to_fp:n {#2}
+            / \dim_to_fp:n { \l_@@_top_dim - \l_@@_bottom_dim }
+          }
+        \fp_set_eq:NN \l_@@_scale_x_fp \l_@@_scale_y_fp
+        \@@_resize:N #1
+      }
+  }
+\cs_new_protected:Npn \box_resize_to_wd:Nn #1#2
+  { \@@_resize_to_wd:NnN #1 {#2} \hbox_set:Nn }
+\cs_generate_variant:Nn \box_resize_to_wd:Nn { c }
+\cs_new_protected:Npn \box_gresize_to_wd:Nn #1#2
+  { \@@_resize_to_wd:NnN #1 {#2} \hbox_gset:Nn }
+\cs_generate_variant:Nn \box_gresize_to_wd:Nn { c }
+\cs_new_protected:Npn \@@_resize_to_wd:NnN #1#2#3
+  {
+    #3 #1
+      {
+        \@@_resize_set_corners:N #1
+        \fp_set:Nn \l_@@_scale_x_fp
+          { \dim_to_fp:n {#2} / \dim_to_fp:n { \l_@@_right_dim } }
+        \fp_set_eq:NN \l_@@_scale_y_fp \l_@@_scale_x_fp
+        \@@_resize:N #1
+      }
+  }
+\cs_new_protected:Npn \box_resize_to_wd_and_ht:Nnn #1#2#3
+  { \@@_resize_to_wd_and_ht:NnnN #1 {#2} {#3} \hbox_set:Nn }
+\cs_generate_variant:Nn \box_resize_to_wd_and_ht:Nnn { c }
+\cs_new_protected:Npn \box_gresize_to_wd_and_ht:Nnn #1#2#3
+  { \@@_resize_to_wd_and_ht:NnnN #1 {#2} {#3} \hbox_gset:Nn }
+\cs_generate_variant:Nn \box_gresize_to_wd_and_ht:Nnn { c }
+\cs_new_protected:Npn \@@_resize_to_wd_and_ht:NnnN #1#2#3#4
+  {
+    #4 #1
+      {
+        \@@_resize_set_corners:N #1
+        \fp_set:Nn \l_@@_scale_x_fp
+          { \dim_to_fp:n {#2} / \dim_to_fp:n { \l_@@_right_dim } }
+        \fp_set:Nn \l_@@_scale_y_fp
+          {
+              \dim_to_fp:n {#3}
+            / \dim_to_fp:n { \l_@@_top_dim }
+          }
+        \@@_resize:N #1
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \box_scale:Nnn, \box_scale:cnn,
+%     \box_gscale:Nnn, \box_gscale:cnn
+%   }
+% \begin{macro}{\@@_scale:NnnN}
+% \begin{macro}{\@@_scale:N}
+%   When scaling a box, setting the scaling itself is easy enough. The
+%   new dimensions are also relatively easy to find, allowing only for
+%   the need to keep them positive in all cases. Once that is done then
+%   after a check for the trivial scaling a hand-off can be made to the
+%   common code. The code here is split into two as this allows sharing
+%   with the auto-resizing functions.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_scale:Nnn #1#2#3
+  { \@@_scale:NnnN #1 {#2} {#3} \hbox_set:Nn }
+\cs_generate_variant:Nn \box_scale:Nnn { c }
+\cs_new_protected:Npn \box_gscale:Nnn #1#2#3
+  { \@@_scale:NnnN #1 {#2} {#3} \hbox_gset:Nn }
+\cs_generate_variant:Nn \box_gscale:Nnn { c }
+\cs_new_protected:Npn \@@_scale:NnnN #1#2#3#4
+  {
+    #4 #1
+      {
+        \fp_set:Nn \l_@@_scale_x_fp {#2}
+        \fp_set:Nn \l_@@_scale_y_fp {#3}
+        \@@_scale:N #1
+      }
+  }
+\cs_new_protected:Npn \@@_scale:N #1
+  {
+    \dim_set:Nn \l_@@_top_dim    {  \box_ht:N #1 }
+    \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
+    \dim_set:Nn \l_@@_right_dim  {  \box_wd:N #1 }
+    \dim_zero:N \l_@@_left_dim
+    \dim_set:Nn \l_@@_top_new_dim
+      { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_top_dim }
+    \dim_set:Nn \l_@@_bottom_new_dim
+      { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_bottom_dim }
+    \dim_set:Nn \l_@@_right_new_dim
+      { \fp_abs:n { \l_@@_scale_x_fp } \l_@@_right_dim }
+    \@@_resize_common:N #1
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \box_autosize_to_wd_and_ht:Nnn          ,
+%     \box_autosize_to_wd_and_ht:cnn          ,
+%     \box_gautosize_to_wd_and_ht:Nnn         ,
+%     \box_gautosize_to_wd_and_ht:cnn         ,
+%     \box_autosize_to_wd_and_ht_plus_dp:Nnn  ,
+%     \box_autosize_to_wd_and_ht_plus_dp:cnn  ,
+%     \box_gautosize_to_wd_and_ht_plus_dp:Nnn ,
+%     \box_gautosize_to_wd_and_ht_plus_dp:cnn
+%   }
+% \begin{macro}{\@@_autosize:NnnnN}
+%   Although autosizing a box uses dimensions, it has more in common in
+%   implementation with scaling. As such, most of the real work here is
+%   done elsewhere.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_autosize_to_wd_and_ht:Nnn #1#2#3
+  { \@@_autosize:NnnnN #1 {#2} {#3} { \box_ht:N #1 } \hbox_set:Nn }
+\cs_generate_variant:Nn \box_autosize_to_wd_and_ht:Nnn { c }
+\cs_new_protected:Npn \box_gautosize_to_wd_and_ht:Nnn #1#2#3
+  { \@@_autosize:NnnnN #1 {#2} {#3} { \box_ht:N #1 } \hbox_gset:Nn }
+\cs_generate_variant:Nn \box_gautosize_to_wd_and_ht:Nnn { c }
+\cs_new_protected:Npn \box_autosize_to_wd_and_ht_plus_dp:Nnn #1#2#3
+  {
+    \@@_autosize:NnnnN #1 {#2} {#3} { \box_ht:N #1 + \box_dp:N #1 }
+      \hbox_set:Nn
+  }
+\cs_generate_variant:Nn \box_autosize_to_wd_and_ht_plus_dp:Nnn { c }
+\cs_new_protected:Npn \box_gautosize_to_wd_and_ht_plus_dp:Nnn #1#2#3
+  {
+    \@@_autosize:NnnnN #1 {#2} {#3} { \box_ht:N #1 + \box_dp:N #1 }
+      \hbox_gset:Nn
+  }
+\cs_generate_variant:Nn \box_gautosize_to_wd_and_ht_plus_dp:Nnn { c }
+\cs_new_protected:Npn \@@_autosize:NnnnN #1#2#3#4#5
+  {
+    #5 #1
+      {
+        \fp_set:Nn \l_@@_scale_x_fp { ( \dim_to_fp:n {#2} ) / \box_wd:N #1 }
+        \fp_set:Nn \l_@@_scale_y_fp
+          { (  \dim_to_fp:n {#3} ) / ( \dim_to_fp:n {#4} ) }
+        \fp_compare:nNnTF \l_@@_scale_x_fp > \l_@@_scale_y_fp
+          { \fp_set_eq:NN \l_@@_scale_x_fp \l_@@_scale_y_fp }
+          { \fp_set_eq:NN \l_@@_scale_y_fp \l_@@_scale_x_fp }
+        \@@_scale:N #1
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_resize_common:N}
+%   The main resize function places its input into a box which start
+%   off with zero width, and includes the handles for engine rescaling.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_resize_common:N #1
+  {
+    \hbox_set:Nn \l_@@_internal_box
+      {
+        \@@_backend_scale:Nnn
+          #1
+          \l_@@_scale_x_fp
+          \l_@@_scale_y_fp
+      }
+%    \end{macrocode}
+%   The new height and depth can be applied directly.
+%    \begin{macrocode}
+    \fp_compare:nNnTF \l_@@_scale_y_fp > \c_zero_fp
+      {
+        \box_set_ht:Nn \l_@@_internal_box { \l_@@_top_new_dim }
+        \box_set_dp:Nn \l_@@_internal_box { -\l_@@_bottom_new_dim }
+      }
+      {
+        \box_set_dp:Nn \l_@@_internal_box { \l_@@_top_new_dim }
+        \box_set_ht:Nn \l_@@_internal_box { -\l_@@_bottom_new_dim }
+      }
+%    \end{macrocode}
+%   Things are not quite as obvious for the width, as the reference point
+%   needs to remain unchanged. For positive scaling factors resizing the
+%   box is all that is needed. However, for case of a negative scaling
+%   the material must be shifted such that the reference point ends up in
+%   the right place.
+%    \begin{macrocode}
+    \fp_compare:nNnTF \l_@@_scale_x_fp < \c_zero_fp
+      {
+        \hbox_to_wd:nn { \l_@@_right_new_dim }
+          {
+            \__kernel_kern:n { \l_@@_right_new_dim }
+            \box_use_drop:N \l_@@_internal_box
+            \tex_hss:D
+          }
+      }
+      {
+        \box_set_wd:Nn \l_@@_internal_box { \l_@@_right_new_dim }
+        \hbox:n
+          {
+            \__kernel_kern:n { 0pt }
+            \box_use_drop:N \l_@@_internal_box
+            \tex_hss:D
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Viewing part of a box}
+%
+% \begin{macro}{\box_set_clipped:N, \box_set_clipped:c, \box_gset_clipped:N, \box_gset_clipped:c}
+%   A wrapper around the driver-dependent code.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_set_clipped:N #1
+  { \hbox_set:Nn #1 { \@@_backend_clip:N #1 } }
+\cs_generate_variant:Nn \box_set_clipped:N { c }
+\cs_new_protected:Npn \box_gset_clipped:N #1
+  { \hbox_gset:Nn #1 { \@@_backend_clip:N #1 } }
+\cs_generate_variant:Nn \box_gset_clipped:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \box_set_trim:Nnnnn, \box_set_trim:cnnnn,
+%     \box_gset_trim:Nnnnn, \box_gset_trim:cnnnn
+%   }
+% \begin{macro}{\@@_set_trim:NnnnnN}
+%   Trimming from the left- and right-hand edges of the box is easy: kern the
+%   appropriate parts off each side.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_set_trim:Nnnnn #1#2#3#4#5
+  { \@@_set_trim:NnnnnN #1 {#2} {#3} {#4} {#5} \box_set_eq:NN }
+\cs_generate_variant:Nn \box_set_trim:Nnnnn { c }
+\cs_new_protected:Npn \box_gset_trim:Nnnnn #1#2#3#4#5
+  { \@@_set_trim:NnnnnN #1 {#2} {#3} {#4} {#5} \box_gset_eq:NN }
+\cs_generate_variant:Nn \box_gset_trim:Nnnnn { c }
+\cs_new_protected:Npn \@@_set_trim:NnnnnN #1#2#3#4#5#6
+  {
+    \hbox_set:Nn \l_@@_internal_box
+      {
+        \__kernel_kern:n { -#2 }
+        \box_use:N #1
+        \__kernel_kern:n { -#4 }
+      }
+%    \end{macrocode}
+%   For the height and depth, there is a need to watch the baseline is
+%   respected. Material always has to stay on the correct side, so trimming
+%   has to check that there is enough material to trim. First, the bottom
+%   edge. If there is enough depth, simply set the depth, or if not move
+%   down so the result is zero depth. \cs{box_move_down:nn} is used in both
+%   cases so the resulting box always contains a \tn{lower} primitive.
+%   The internal box is used here as it allows safe use of \cs{box_set_dp:Nn}.
+%    \begin{macrocode}
+    \dim_compare:nNnTF { \box_dp:N #1 } > {#3}
+      {
+        \hbox_set:Nn \l_@@_internal_box
+          {
+            \box_move_down:nn \c_zero_dim
+              { \box_use_drop:N \l_@@_internal_box }
+          }
+        \box_set_dp:Nn \l_@@_internal_box { \box_dp:N #1 - (#3) }
+      }
+      {
+        \hbox_set:Nn \l_@@_internal_box
+          {
+            \box_move_down:nn { (#3) - \box_dp:N #1 }
+              { \box_use_drop:N \l_@@_internal_box }
+          }
+        \box_set_dp:Nn \l_@@_internal_box \c_zero_dim
+      }
+%    \end{macrocode}
+%   Same thing, this time from the top of the box.
+%    \begin{macrocode}
+    \dim_compare:nNnTF { \box_ht:N \l_@@_internal_box } > {#5}
+      {
+        \hbox_set:Nn \l_@@_internal_box
+          {
+            \box_move_up:nn \c_zero_dim
+              { \box_use_drop:N \l_@@_internal_box }
+          }
+        \box_set_ht:Nn \l_@@_internal_box
+          { \box_ht:N \l_@@_internal_box - (#5) }
+      }
+      {
+        \hbox_set:Nn \l_@@_internal_box
+          {
+            \box_move_up:nn { (#5) - \box_ht:N \l_@@_internal_box }
+              { \box_use_drop:N \l_@@_internal_box }
+          }
+        \box_set_ht:Nn \l_@@_internal_box \c_zero_dim
+      }
+    #6 #1 \l_@@_internal_box
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \box_set_viewport:Nnnnn, \box_set_viewport:cnnnn,
+%     \box_gset_viewport:Nnnnn, \box_gset_viewport:cnnnn
+%   }
+% \begin{macro}{\@@_viewport:NnnnnN}
+%   The same general logic as for the trim operation, but with absolute
+%   dimensions. As a result, there are some things to watch out for in the
+%   vertical direction.
+%    \begin{macrocode}
+\cs_new_protected:Npn \box_set_viewport:Nnnnn #1#2#3#4#5
+  { \@@_set_viewport:NnnnnN #1 {#2} {#3} {#4} {#5} \box_set_eq:NN }
+\cs_generate_variant:Nn \box_set_viewport:Nnnnn { c }
+\cs_new_protected:Npn \box_gset_viewport:Nnnnn #1#2#3#4#5
+  { \@@_set_viewport:NnnnnN #1 {#2} {#3} {#4} {#5} \box_gset_eq:NN }
+\cs_generate_variant:Nn \box_gset_viewport:Nnnnn { c }
+\cs_new_protected:Npn \@@_set_viewport:NnnnnN #1#2#3#4#5#6
+  {
+    \hbox_set:Nn \l_@@_internal_box
+      {
+        \__kernel_kern:n { -#2 }
+        \box_use:N #1
+        \__kernel_kern:n { #4 - \box_wd:N #1 }
+      }
+    \dim_compare:nNnTF {#3} < \c_zero_dim
+      {
+        \hbox_set:Nn \l_@@_internal_box
+          {
+            \box_move_down:nn \c_zero_dim
+              { \box_use_drop:N \l_@@_internal_box }
+          }
+        \box_set_dp:Nn \l_@@_internal_box { - \@@_dim_eval:n {#3} }
+      }
+      {
+        \hbox_set:Nn \l_@@_internal_box
+          { \box_move_down:nn {#3} { \box_use_drop:N \l_@@_internal_box } }
+        \box_set_dp:Nn \l_@@_internal_box \c_zero_dim
+      }
+    \dim_compare:nNnTF {#5} > \c_zero_dim
+      {
+        \hbox_set:Nn \l_@@_internal_box
+          {
+            \box_move_up:nn \c_zero_dim
+              { \box_use_drop:N \l_@@_internal_box }
+          }
+        \box_set_ht:Nn \l_@@_internal_box
+          {
+            (#5)
+            \dim_compare:nNnT {#3} > \c_zero_dim
+              { - (#3) }
+          }
+      }
+      {
+        \hbox_set:Nn \l_@@_internal_box
+          {
+            \box_move_up:nn { - \@@_dim_eval:n {#5} }
+              { \box_use_drop:N \l_@@_internal_box }
+          }
+        \box_set_ht:Nn \l_@@_internal_box \c_zero_dim
+      }
+    #6 #1 \l_@@_internal_box
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3box.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3cctab.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3cctab.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3cctab.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,975 @@
+% \iffalse meta-comment
+%
+%% File: l3cctab.dtx
+%
+% Copyright (C) 2018-2024 The LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version.  The latest version
+% of this license is in the file
+%
+%    http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+%    https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+%   The \pkg{l3cctab} module\\ Category code tables^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% A category code table enables rapid switching of all category codes in
+% one operation. For \LuaTeX{}, this is possible over the entire Unicode
+% range. For other engines, only the $8$-bit range ($0$--$255$) is covered by
+% such tables. The implementation of category code tables in \pkg{expl3}
+% also saves and restores the \TeX{} \tn{endlinechar} primitive value, meaning
+% they could be used for example to implement \cs{ExplSyntaxOn}.
+%
+% \section{Creating and initialising category code tables}
+%
+% \begin{function}[updated = 2020-07-02]{\cctab_new:N,\cctab_new:c}
+%   \begin{syntax}
+%     \cs{cctab_new:N} \meta{category code table}
+%   \end{syntax}
+%   Creates a new \meta{category code table} variable or raises an error if
+%   the name is already taken. The declaration is global.  The
+%   \meta{category code table} is initialised with the codes
+%   as used by \IniTeX{}.
+% \end{function}
+%
+% \begin{function}[updated = 2020-07-07]{\cctab_const:Nn,\cctab_const:cn}
+%   \begin{syntax}
+%     \cs{cctab_const:Nn} \meta{category code table} \Arg{category code set up}
+%   \end{syntax}
+%   Creates a new \meta{category code table}, applies (in a group) the
+%   \meta{category code set up} on top of \IniTeX{} settings,
+%   then saves them globally as a constant
+%   table.  The \meta{category code set up} can include a call to
+%   \cs{cctab_select:N}.
+% \end{function}
+%
+% \begin{function}[updated = 2020-07-07]{\cctab_gset:Nn,\cctab_gset:cn}
+%   \begin{syntax}
+%     \cs{cctab_gset:Nn} \meta{category code table} \Arg{category code set up}
+%   \end{syntax}
+%   Starting from the \IniTeX{} category codes,
+%   applies (in a group) the \meta{category code set up}, then saves them
+%   globally in the \meta{category code table}.  The \meta{category code set up}
+%   can include a call to \cs{cctab_select:N}.
+% \end{function}
+%
+% \begin{function}[added = 2023-05-26]
+%   {\cctab_gsave_current:N,\cctab_gsave_current:c}
+%   \begin{syntax}
+%     \cs{cctab_gsave_current:N} \meta{category code table}
+%   \end{syntax}
+%   Saves the current prevailing category codes in the
+%   \meta{category code table}.
+% \end{function}
+%
+% \section{Using category code tables}
+%
+% \begin{function}[updated = 2020-07-02]{\cctab_begin:N,\cctab_begin:c}
+%   \begin{syntax}
+%     \cs{cctab_begin:N} \meta{category code table}
+%   \end{syntax}
+%   Switches locally the category codes in force to those stored in the
+%   \meta{category code table}.  The prevailing codes before the
+%   function is called are added to a stack, for use with
+%   \cs{cctab_end:}. This function does not start a \TeX{} group.
+% \end{function}
+%
+% \begin{function}[updated = 2020-07-02]{\cctab_end:}
+%   \begin{syntax}
+%     \cs{cctab_end:}
+%   \end{syntax}
+%   Ends the scope of a \meta{category code table} started using
+%   \cs{cctab_begin:N}, returning the codes to those in force before the
+%   matching \cs{cctab_begin:N} was used.  This must be used within the
+%   same \TeX{} group (and at the same \TeX{} group level) as the
+%   matching \cs{cctab_begin:N}.
+% \end{function}
+%
+% \begin{function}[added = 2020-05-19, updated = 2020-07-02]{\cctab_select:N, \cctab_select:c}
+%   \begin{syntax}
+%     \cs{cctab_select:N} \meta{category code table}
+%   \end{syntax}
+%   Selects the \meta{category code table} for the scope of the current
+%   group.  This is in particular useful in the \meta{setup} arguments
+%   of \cs{tl_set_rescan:Nnn}, \cs{tl_rescan:nn}, \cs{cctab_const:Nn},
+%   and \cs{cctab_gset:Nn}.
+% \end{function}
+%
+% \begin{function}[EXP, added = 2021-05-10]{\cctab_item:Nn, \cctab_item:cn}
+%   \begin{syntax}
+%     \cs{cctab_item:Nn} \meta{category code table} \Arg{int expr}
+%   \end{syntax}
+%   Determines the \meta{character} with character code given by the
+%   \meta{int expr} and expands to its category code specified
+%   by the \meta{category code table}.
+% \end{function}
+%
+% \section{Category code table conditionals}
+%
+% \begin{function}[pTF]{\cctab_if_exist:N, \cctab_if_exist:c}
+%   \begin{syntax}
+%     \cs{cctab_if_exist_p:N} \meta{category code table}
+%     \cs{cctab_if_exist:NTF} \meta{category code table} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{category code table} is currently defined.
+%   This does not check that the \meta{category code table} really is a
+%   category code table.
+% \end{function}
+%
+% \section{Constant and scratch category code tables}
+%
+% \begin{variable}[updated = 2020-07-10]{\c_code_cctab}
+%   Category code table for the \pkg{expl3} code environment; this does
+%   \emph{not} include \texttt{@}, which is retained as an \enquote{other}
+%   character.  Sets the \tn{endlinechar} value to $32$ (a space).
+% \end{variable}
+%
+% \begin{variable}[updated = 2020-07-08]{\c_document_cctab}
+%   Category code table for a standard \LaTeX{} document, as set by the \LaTeX{}
+%   kernel. In particular, the upper-half of the $8$-bit range will be set to
+%   \enquote{active} with \pdfTeX{} \emph{only}. No \pkg{babel} shorthands
+%   will be activated.  Sets the \tn{endlinechar} value to $13$ (normal
+%   line ending).
+% \end{variable}
+%
+% \begin{variable}[updated = 2020-07-02]{\c_initex_cctab}
+%   Category code table as set up by \IniTeX{}.
+% \end{variable}
+%
+% \begin{variable}[updated = 2020-07-02]{\c_other_cctab}
+%   Category code table where all characters have category code $12$
+%   (other). Sets the \tn{endlinechar} value to $-1$.
+% \end{variable}
+%
+% \begin{variable}[updated = 2020-07-02]{\c_str_cctab}
+%   Category code table where all characters have category code $12$
+%   (other) with the exception of spaces, which have category code
+%   $10$ (space).  Sets the \tn{endlinechar} value to $-1$.
+% \end{variable}
+%
+% \begin{variable}[added = 2023-05-26]{\g_tmpa_cctab, \g_tmpb_cctab}
+%   Scratch category code tables.
+% \end{variable}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3cctab} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=cctab>
+%    \end{macrocode}
+%
+% As \LuaTeX{} offers engine support for category code tables, and this
+% is entirely lacking from the other engines, we need two complementary
+% approaches. (Some future \XeTeX{} may add support, at which point the
+% conditionals below would be different.)
+%
+% \subsection{Variables}
+%
+% \begin{variable}{\g_@@_stack_seq, \g_@@_unused_seq}
+%   List of catcode tables saved by nested \cs{cctab_begin:N}, to
+%   restore catcodes at the matching \cs{cctab_end:}.  When popped from
+%   the \cs{g_@@_stack_seq} the table numbers are stored in
+%   \cs{g_@@_unused_seq} for later reuse.
+%    \begin{macrocode}
+\seq_new:N \g_@@_stack_seq
+\seq_new:N \g_@@_unused_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_group_seq}
+%   A stack to store the group level when a catcode table started.
+%    \begin{macrocode}
+\seq_new:N \g_@@_group_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_allocate_int}
+%   Integer to keep track of what category code table to allocate.  In
+%   \LuaTeX{} it is only used in format mode to implement
+%   \cs{cctab_new:N}.  In other engines it is used to make csnames for
+%   dynamic tables.
+%    \begin{macrocode}
+\int_new:N  \g_@@_allocate_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_internal_a_tl,\l_@@_internal_b_tl}
+%   Scratch space.  For instance, when popping
+%   \cs{g_@@_stack_seq}/\cs{g_@@_unused_seq}, consists of the
+%   catcodetable number (integer denotation) in \LuaTeX{}, or of an
+%   intarray variable (as a single token) in other engines.
+%    \begin{macrocode}
+\tl_new:N \l_@@_internal_a_tl
+\tl_new:N \l_@@_internal_b_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_endlinechar_prop}
+%   In \LuaTeX{} we store the \tn{endlinechar} associated to each
+%   \tn{catcodetable} in a property list, unless it is the default
+%   value~$13$.
+%    \begin{macrocode}
+\prop_new:N \g_@@_endlinechar_prop
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Allocating category code tables}
+%
+% \begin{macro}{\cctab_new:N, \cctab_new:c, \@@_new:N, \@@_gstore:Nnn}
+%   The \cs{@@_new:N} auxiliary allocates a new catcode table but does
+%   not attempt to set its value consistently across engines.  It is
+%   used both in \cs{cctab_new:N}, which sets catcodes to \IniTeX{}
+%   values, and in \cs{cctab_begin:N}/\cs{cctab_end:} for dynamically
+%   allocated tables.
+%
+%   First, the \LuaTeX{} case.
+%   Creating a new category code table is done like other registers.
+%   In Con\TeX{}t, \tn{newcatcodetable} does not include the initialisation,
+%   so that is added explicitly.
+%    \begin{macrocode}
+\sys_if_engine_luatex:TF
+  {
+    \cs_new_protected:Npn \cctab_new:N #1
+      {
+        \__kernel_chk_if_free_cs:N #1
+        \@@_new:N #1
+      }
+    \cs_new_protected:Npn \@@_new:N #1
+      {
+        \newcatcodetable #1
+        \tex_initcatcodetable:D #1
+      }
+  }
+%    \end{macrocode}
+%   Now the case for other engines. Here, each table is an integer
+%   array.  Following the \LuaTeX{} pattern, a new table starts with
+%   \IniTeX{} codes.  The \cs{debug_suspend:} and \cs{debug_resume:}
+%   functions prevent errors and logging from \texttt{debug} commands
+%   which are either duplicate or false when \cs{@@_new:N} is used
+%   by \cs{cctab_new:N} or \cs{cctab_const:Nn}.
+%   The index base is out-by-one, so we have an
+%   internal function to handle that.  The \IniTeX{} \tn{endlinechar} is
+%   $13$.
+%    \begin{macrocode}
+  {
+    \cs_new_protected:Npn \@@_new:N #1
+      {
+        \debug_suspend:
+        \intarray_new:Nn #1 { 257 }
+        \debug_resume:
+      }
+    \cs_new_protected:Npn \@@_gstore:Nnn #1#2#3
+      { \intarray_gset:Nnn #1 { #2 + 1 } {#3} }
+    \cs_new_protected:Npn \cctab_new:N #1
+      {
+        \__kernel_chk_if_free_cs:N #1
+        \@@_new:N #1
+        \int_step_inline:nn { 256 }
+          { \__kernel_intarray_gset:Nnn #1 {##1} { 12 } }
+        \__kernel_intarray_gset:Nnn #1 { 257 } { 13 }
+        \@@_gstore:Nnn #1 { 0 } { 9 }
+        \@@_gstore:Nnn #1 { 13 } { 5 }
+        \@@_gstore:Nnn #1 { 32 } { 10 }
+        \@@_gstore:Nnn #1 { 37 } { 14 }
+        \int_step_inline:nnn { 65 } { 90 }
+          { \@@_gstore:Nnn #1 {##1} { 11 } }
+        \@@_gstore:Nnn #1 { 92 } { 0 }
+        \int_step_inline:nnn { 97 } { 122 }
+          { \@@_gstore:Nnn #1 {##1} { 11 } }
+        \@@_gstore:Nnn #1 { 127 } { 15 }
+      }
+  }
+\cs_generate_variant:Nn \cctab_new:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Saving category code tables}
+%
+% \begin{macro}{\@@_gset:n, \@@_gset_aux:n}
+%   In various functions we need to save the current catcodes (globally)
+%   in a table.  In \LuaTeX{}, saving the catcodes is a primitives, but
+%   the \tn{endlinechar} needs more work: to avoid filling
+%   \cs{g_@@_endlinechar_prop} with many entries we special-case the
+%   default value $13$.  In other engines we store $256$ current
+%   catcodes and the \tn{endlinechar} in an intarray variable.
+%    \begin{macrocode}
+\sys_if_engine_luatex:TF
+  {
+    \cs_new_protected:Npn \@@_gset:n #1
+      { \exp_args:Nf \@@_gset_aux:n { \int_eval:n {#1} } }
+    \cs_new_protected:Npn \@@_gset_aux:n #1
+      {
+        \tex_savecatcodetable:D #1 \scan_stop:
+        \int_compare:nNnTF { \tex_endlinechar:D } = { 13 }
+          { \prop_gremove:Nn \g_@@_endlinechar_prop {#1} }
+          {
+            \prop_gput:NnV \g_@@_endlinechar_prop {#1}
+              \tex_endlinechar:D
+          }
+      }
+  }
+  {
+    \cs_new_protected:Npn \@@_gset:n #1
+      {
+        \int_step_inline:nn { 256 }
+          {
+            \__kernel_intarray_gset:Nnn #1 {##1}
+              { \char_value_catcode:n { ##1 - 1 } }
+          }
+        \__kernel_intarray_gset:Nnn #1 { 257 }
+          { \tex_endlinechar:D }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\cctab_gset:Nn, \cctab_gset:cn}
+%   Category code tables are always global, so only one version of
+%   assignments is needed.  Simply run the setup in a group and save the
+%   result in a category code table~|#1|, provided it is valid.  The
+%   internal function is defined above depending on the engine.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cctab_gset:Nn #1#2
+  {
+    \@@_chk_if_valid:NT #1
+      {
+        \group_begin:
+          \cctab_select:N \c_initex_cctab
+          #2 \scan_stop:
+          \@@_gset:n {#1}
+        \group_end:
+      }
+  }
+\cs_generate_variant:Nn \cctab_gset:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\cctab_gsave_current:N, \cctab_gsave_current:c}
+%   Very simple.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cctab_gsave_current:N #1
+  {
+    \@@_chk_if_valid:NT #1
+      { \@@_gset:n {#1} }
+  }
+\cs_generate_variant:Nn \cctab_gsave_current:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Using category code tables}
+%
+% \begin{variable}{\g_@@_internal_cctab}
+% \begin{macro}[EXP]{\@@_internal_cctab_name:}
+%   In \LuaTeX{}, we must ensure that the saved tables are read-only.
+%   This is done by applying the saved table, then switching immediately
+%   to a scratch table.  Any later catcode assignment will affect that
+%   scratch table rather than the saved one.  If we simply switched to
+%   the saved tables, then \cs{char_set_catcode_other:N} in the example
+%   below would change \cs{c_document_cctab} and a later use of that
+%   table would give the wrong category code to |_|.
+% \begin{verbatim}
+% \use:n
+%   {
+%     \cctab_begin:N \c_document_cctab
+%       \char_set_catcode_other:N \_
+%     \cctab_end:
+%     \cctab_begin:N \c_document_cctab
+%       \int_compare:nTF { \char_value_catcode:n { `_ } = 8 }
+%         { \TRUE } { \ERROR }
+%     \cctab_end:
+%   }
+% \end{verbatim}
+%   We must also make sure that a scratch table is never reused in a
+%   nested group: in the following example, the scratch table used by
+%   the first \cs{cctab_begin:N} would be changed globally by the second
+%   one issuing \tn{savecatcodetable}, and after \cs{group_end:} the
+%   wrong category codes (those of \cs{c_str_cctab}) would be imposed.
+%   Note that the inner \cs{cctab_end:} restores the correct catcodes
+%   only locally, so the problem really comes up because of the
+%   different grouping level.  The simplest is to use a scratch table
+%   labeled by the \tn{currentgrouplevel}.  We initialize one of them as
+%   an example.
+% \begin{verbatim}
+% \use:n
+%   {
+%     \cctab_begin:N \c_document_cctab
+%       \group_begin:
+%         \cctab_begin:N \c_str_cctab
+%         \cctab_end:
+%       \group_end:
+%     \cctab_end:
+%   }
+% \end{verbatim}
+%    \begin{macrocode}
+\sys_if_engine_luatex:T
+  {
+    \@@_new:N \g_@@_internal_cctab
+    \cs_new:Npn \@@_internal_cctab_name:
+      {
+        g_@@_internal
+        \tex_romannumeral:D \tex_currentgrouplevel:D
+        _cctab
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{variable}
+%
+% \begin{macro}{\cctab_select:N, \cctab_select:c}
+% \begin{macro}{\@@_select:N}
+%   The public function simply checks the \meta{cctab~var} exists before
+%   using the engine-dependent \cs{@@_select:N}.  Skipping these checks
+%   would result in low-level engine-dependent errors.  First, the
+%   \LuaTeX{} case.  In other engines, selecting a catcode table is a matter
+%   of doing $256$ catcode assignments and setting the \tn{endlinechar}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cctab_select:N #1
+  { \@@_chk_if_valid:NT #1 { \@@_select:N #1 } }
+\cs_generate_variant:Nn \cctab_select:N { c }
+\sys_if_engine_luatex:TF
+  {
+    \cs_new_protected:Npn \@@_select:N #1
+      {
+        \tex_catcodetable:D #1
+        \prop_get:NVNTF \g_@@_endlinechar_prop #1 \l_@@_internal_a_tl
+          { \int_set:Nn \tex_endlinechar:D { \l_@@_internal_a_tl } }
+          { \int_set:Nn \tex_endlinechar:D { 13 } }
+        \cs_if_exist:cF { \@@_internal_cctab_name: }
+          { \exp_args:Nc \@@_new:N { \@@_internal_cctab_name: } }
+        \exp_args:Nc \tex_savecatcodetable:D { \@@_internal_cctab_name: }
+        \exp_args:Nc \tex_catcodetable:D { \@@_internal_cctab_name: }
+      }
+  }
+  {
+    \cs_new_protected:Npn \@@_select:N #1
+      {
+        \int_step_inline:nn { 256 }
+          {
+            \char_set_catcode:nn { ##1 - 1 }
+              { \__kernel_intarray_item:Nn #1 {##1} }
+          }
+        \int_set:Nn \tex_endlinechar:D
+          { \__kernel_intarray_item:Nn #1 { 257 } }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\g_@@_next_cctab}
+% \begin{macro}{\@@_begin_aux:}
+%   For \cs{cctab_begin:N}/\cs{cctab_end:} we will need to allocate
+%   dynamic tables.  This is done here by \cs{@@_begin_aux:}, which puts
+%   a table number (in \LuaTeX{}) or name (in other engines) into
+%   \cs{l_@@_internal_a_tl}.  In \LuaTeX{} this simply calls \cs{@@_new:N}
+%   and uses the resulting catcodetable number; in other engines we need
+%   to give a name to the intarray variable and use that.  In \LuaTeX{},
+%   to restore catcodes at \cs{cctab_end:} we cannot just set
+%   \tn{catcodetable} to its value before \cs{cctab_begin:N}, because
+%   that table may have been altered by other code in the mean time.  So
+%   we must make sure to save the catcodes in a table we control and
+%   restore them at \cs{cctab_end:}.
+%    \begin{macrocode}
+\sys_if_engine_luatex:TF
+  {
+    \cs_new_protected:Npn \@@_begin_aux:
+      {
+        \@@_new:N \g_@@_next_cctab
+        \tl_set:NV \l_@@_internal_a_tl \g_@@_next_cctab
+        \cs_undefine:N \g_@@_next_cctab
+      }
+  }
+  {
+    \cs_new_protected:Npn \@@_begin_aux:
+      {
+        \int_gincr:N \g_@@_allocate_int
+        \exp_args:Nc \@@_new:N
+          { g_@@_ \int_use:N \g_@@_allocate_int _cctab }
+        \exp_args:NNc \tl_set:Nn \l_@@_internal_a_tl
+          { g_@@_ \int_use:N \g_@@_allocate_int _cctab }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{variable}
+%
+% \begin{macro}{\cctab_begin:N, \cctab_begin:c}
+%   Check the \meta{cctab~var} exists, to avoid low-level errors.  Get
+%   in \cs{l_@@_internal_a_tl} the number/name of a dynamic table, either
+%   from \cs{g_@@_unused_seq} where we save tables that are not
+%   currently in use, or from \cs{@@_begin_aux:} if none are available.
+%   Then save the current catcodes into the table (pointed to by)
+%   \cs{l_@@_internal_a_tl} and save that table number in a stack before
+%   selecting the desired catcodes.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cctab_begin:N #1
+  {
+    \@@_chk_if_valid:NT #1
+      {
+        \seq_gpop:NNF \g_@@_unused_seq \l_@@_internal_a_tl
+          { \@@_begin_aux: }
+        \@@_chk_group_begin:e
+          { \@@_nesting_number:N \l_@@_internal_a_tl }
+        \seq_gpush:NV \g_@@_stack_seq \l_@@_internal_a_tl
+        \exp_args:NV \@@_gset:n \l_@@_internal_a_tl
+        \@@_select:N #1
+      }
+  }
+\cs_generate_variant:Nn \cctab_begin:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\cctab_end:}
+%   Make sure a \cs{cctab_begin:N} was used some time earlier, get in
+%   \cs{l_@@_internal_a_tl} the catcode table number/name in which the
+%   prevailing catcodes were stored, then restore these catcodes.  The
+%   dynamic table is now unused hence stored in \cs{g_@@_unused_seq} for
+%   recycling by later \cs{cctab_begin:N}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cctab_end:
+  {
+    \seq_gpop:NNTF \g_@@_stack_seq \l_@@_internal_a_tl
+      {
+        \seq_gpush:NV \g_@@_unused_seq \l_@@_internal_a_tl
+        \exp_args:Ne \@@_chk_group_end:n
+          { \@@_nesting_number:N \l_@@_internal_a_tl }
+        \@@_select:N \l_@@_internal_a_tl
+      }
+      { \msg_error:nn { cctab } { extra-end } }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {\@@_chk_group_begin:n,\@@_chk_group_begin:e, \@@_chk_group_end:n}
+%   Catcode tables are not allowed to be intermixed with groups, so here
+%   we check that they are properly nested regarding \TeX{} groups.
+%   \cs{@@_chk_group_begin:n} stores the current group level in a stack,
+%   and locally defines a dummy control sequence
+%   \cs[no-index]{@@_group_\meta{cctab-level}_chk:}.
+%
+%   \cs{@@_chk_group_end:n} pops the stack, and compares the returned
+%   value with \cs{tex_currentgrouplevel:D}.  If they differ,
+%   \cs{cctab_end:} is in a different grouping level than the matching
+%   \cs{cctab_begin:N}.  If they are the same, both happened at the same
+%   level, however a group might have ended and another started between
+%   \cs{cctab_begin:N} and \cs{cctab_end:}:
+% \begin{verbatim}
+%   \group_begin:
+%     \cctab_begin:N \c_document_cctab
+%   \group_end:
+%   \group_begin:
+%     \cctab_end:
+%   \group_end:
+% \end{verbatim}
+%   In this case checking \cs{tex_currentgrouplevel:D} is not enough, so
+%   we locally define \cs[no-index]{@@_group_\meta{cctab-level}_chk:},
+%   and then check if it exist in \cs{cctab_end:}.  If it doesn't,
+%   we know there was a group end where it shouldn't.
+%
+%   The \meta{cctab-level} in the sentinel macro above cannot be
+%   replaced by the more convenient \cs{tex_currentgrouplevel:D} because
+%   with the latter we might be tricked.  Suppose:
+% \begin{verbatim}
+%   \group_begin:
+%     \cctab_begin:N \c_code_cctab % A
+%   \group_end:
+%   \group_begin:
+%     \cctab_begin:N \c_code_cctab % B
+%     \cctab_end: % C
+%     \cctab_end: % D
+%   \group_end:
+% \end{verbatim}
+%   The line marked with |A| would start a |cctab| with a sentinel token
+%   named \cs[no-index]{@@_group_1_chk:}, which would disappear at the
+%   \cs{group_end:} that follows.  But |B| would create the same
+%   sentinel token, since both are at the same group level.  Line |C|
+%   would end the |cctab| from line |B| correctly, but so would line |D|
+%   because line |B| created the same sentinel token.  Using
+%   \meta{cctab-level} works correctly because it signals that certain
+%   |cctab| level was activated somewhere, but if it doesn't exist when
+%   the \cs{cctab_end:} is reached, we had a problem.
+%
+%   Unfortunately these tests only flag the wrong usage at the
+%   \cs{cctab_end:}, which might be far from the \cs{cctab_begin:N}.
+%   However it isn't possible to signal the wrong usage at the
+%   \cs{group_end:} without using \cs{tex_aftergroup:D}, which is
+%   unsafe in certain types of groups.
+%
+%   The three cases checked here just raise an error, and no recovery is
+%   attempted:  usually interleaving groups and catcode tables will work
+%   predictably.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_chk_group_begin:n #1
+  {
+    \seq_gpush:Ne \g_@@_group_seq
+      { \int_use:N \tex_currentgrouplevel:D }
+    \cs_set_eq:cN { @@_group_ #1 _chk: } \prg_do_nothing:
+  }
+\cs_generate_variant:Nn \@@_chk_group_begin:n { e }
+\cs_new_protected:Npn \@@_chk_group_end:n #1
+  {
+    \seq_gpop:NN \g_@@_group_seq \l_@@_internal_b_tl
+    \bool_lazy_and:nnF
+      {
+        \int_compare_p:nNn
+          { \tex_currentgrouplevel:D } = { \l_@@_internal_b_tl }
+      }
+      { \cs_if_exist_p:c { @@_group_ #1 _chk: } }
+      {
+        \msg_error:nne { cctab } { group-mismatch }
+          {
+            \int_sign:n
+              { \tex_currentgrouplevel:D - \l_@@_internal_b_tl }
+          }
+      }
+    \cs_undefine:c { @@_group_ #1 _chk: }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_nesting_number:N,\@@_nesting_number:w}
+%   This macro returns the numeric index of the current catcode table.
+%   In \LuaTeX{} this is just the argument, which is a count reference
+%   to a \tn{catcodetable} register.  In other engines, the number is
+%   extracted from the |cctab| variable.
+%    \begin{macrocode}
+\sys_if_engine_luatex:TF
+  { \cs_new:Npn \@@_nesting_number:N #1 {#1} }
+  {
+    \cs_new:Npn \@@_nesting_number:N #1
+      {
+        \exp_after:wN \exp_after:wN \exp_after:wN \@@_nesting_number:w
+          \exp_after:wN \token_to_str:N #1
+      }
+    \use:e
+      {
+        \cs_new:Npn \exp_not:N \@@_nesting_number:w
+          #1 \tl_to_str:n { g_@@_ } #2 \tl_to_str:n { _cctab } {#2}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% Finally, install some code at the end of the \TeX{} run to check that
+% all \cs{cctab_begin:N} were ended by some \cs{cctab_end:}.
+%    \begin{macrocode}
+\cs_if_exist:NT \hook_gput_code:nnn
+  {
+    \hook_gput_code:nnn { enddocument/end } { cctab }
+      {
+        \seq_if_empty:NF \g_@@_stack_seq
+          { \msg_error:nn { cctab } { missing-end } }
+      }
+  }
+%    \end{macrocode}
+%
+%
+% \begin{macro}{\cctab_item:Nn, \cctab_item:cn}
+%   Evaluate the integer argument only once.  In most engines the
+%   |cctab| variable only has $256$ entries so we only look up the
+%   catcode for these entries, otherwise we use the current catcode.  In
+%   particular, for out-of-range values we use whatever fall-back
+%   \cs{char_value_catcode:n}.  In \LuaTeX{}, we use the
+%   |tex.getcatcode| function.
+%    \begin{macrocode}
+\cs_new:Npn \cctab_item:Nn #1#2
+  { \exp_args:Nf \@@_item:nN { \int_eval:n {#2} } #1 }
+\sys_if_engine_luatex:TF
+  {
+    \cs_new:Npn \@@_item:nN #1#2
+      { \lua_now:e { tex.print(-2, tex.getcatcode(\int_use:N #2, #1)) } }
+  }
+  {
+    \cs_new:Npn \@@_item:nN #1#2
+      {
+        \int_compare:nNnTF {#1} < { 256 }
+          { \intarray_item:Nn #2 { #1 + 1 } }
+          { \char_value_catcode:n {#1} }
+      }
+  }
+\cs_generate_variant:Nn \cctab_item:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Category code table conditionals}
+%
+% \begin{macro}[pTF]{\cctab_if_exist:N,\cctab_if_exist:c}
+%   Checks whether a \meta{cctab~var} is defined.
+%    \begin{macrocode}
+\prg_new_eq_conditional:NNn \cctab_if_exist:N \cs_if_exist:N
+  { TF , T , F , p }
+\prg_new_eq_conditional:NNn \cctab_if_exist:c \cs_if_exist:c
+  { TF , T , F , p }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF]{\@@_chk_if_valid:N}
+% \begin{macro}{\@@_chk_if_valid_aux:NTF}
+%   Checks whether the argument is defined and whether it is a valid
+%   \meta{cctab~var}. In \LuaTeX{} the validity of the \meta{cctab~var}
+%   is checked by the engine, which complains if the argument is not a
+%   \cs{chardef}'ed constant. In other engines, check if the given
+%   command is an intarray variable (the underlying definition is a copy
+%   of the \texttt{cmr10} font).
+%    \begin{macrocode}
+\prg_new_protected_conditional:Npnn \@@_chk_if_valid:N #1
+  { TF , T , F }
+  {
+    \cctab_if_exist:NTF #1
+      {
+        \@@_chk_if_valid_aux:NTF #1
+          { \prg_return_true: }
+          {
+            \msg_error:nne { cctab } { invalid-cctab }
+              { \token_to_str:N #1 }
+            \prg_return_false:
+          }
+      }
+      {
+        \msg_error:nne { kernel } { command-not-defined }
+          { \token_to_str:N #1 }
+        \prg_return_false:
+      }
+  }
+\sys_if_engine_luatex:TF
+  {
+    \cs_new_protected:Npn \@@_chk_if_valid_aux:NTF #1
+      {
+        \int_compare:nNnTF {#1-1} < { \e at alloc@ccodetable at count }
+      }
+    \cs_if_exist:NT \c_syst_catcodes_n
+      {
+        \cs_gset_protected:Npn \@@_chk_if_valid_aux:NTF #1
+          {
+            \int_compare:nTF { #1 <= \c_syst_catcodes_n }
+          }
+      }
+  }
+  {
+    \cs_new_protected:Npn \@@_chk_if_valid_aux:NTF #1
+      {
+        \exp_args:Nf \str_if_in:nnTF
+          { \cs_meaning:N #1 }
+          { select~font~cmr10~at~ }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Constant category code tables}
+%
+% \begin{macro}{\cctab_const:Nn,\cctab_const:cn}
+%  Creates a new \meta{cctab~var} then sets it with the \IniTeX{} and
+%  user-supplied codes. To avoid false \texttt{debug} errors, we write
+%  out implementation of \cs{cctab_new:N} and \cs{cctab_gset:Nn}
+%  instead of directly using them here. The initialization part in
+%  \cs{cctab_new:N} in non-\LuaTeX{} is omitted as it's covered by
+%  the \IniTeX{} settings.
+%    \begin{macrocode}
+\cs_new_protected:Npn \cctab_const:Nn #1#2
+  {
+    \__kernel_chk_if_free_cs:N #1
+    \@@_new:N #1
+    \group_begin:
+      \cctab_select:N \c_initex_cctab
+      #2 \scan_stop:
+      \@@_gset:n {#1}
+    \group_end:
+  }
+\cs_generate_variant:Nn \cctab_const:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}
+%   {
+%     \c_initex_cctab   ,
+%     \c_other_cctab    ,
+%     \c_str_cctab
+%   }
+%   Creating category code tables means thinking starting from \IniTeX{}.
+%   For all-other and the standard \enquote{string} tables that's easy.
+%    \begin{macrocode}
+\cctab_new:N \c_initex_cctab
+\cctab_const:Nn \c_other_cctab
+  {
+    \cctab_select:N \c_initex_cctab
+    \int_set:Nn \tex_endlinechar:D     { -1 }
+    \int_step_inline:nnn { 0 } { 127 }
+      { \char_set_catcode_other:n {#1} }
+  }
+\cctab_const:Nn \c_str_cctab
+  {
+    \cctab_select:N \c_other_cctab
+    \char_set_catcode_space:n { 32 }
+  }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_code_cctab, \c_document_cctab}
+%  To pick up document-level category codes, we need to delay set up to the
+%  end of the format, where that's possible. Also, as there are a \emph{lot}
+%  of category codes to set, we avoid using the official interface and store the
+%  document codes using internal code. Depending on whether we are in the hook
+%  or not, the catcodes may be code or document, so we explicitly set up both
+%  correctly.
+%    \begin{macrocode}
+\cs_if_exist:NTF \@expl at finalise@setup@@@@
+  { \tl_gput_right:Nn \@expl at finalise@setup@@@@ }
+  { \use:n }
+  {
+    \@@_new:N \c_code_cctab
+    \group_begin:
+      \int_set:Nn \tex_endlinechar:D { 32 }
+      \char_set_catcode_invalid:n { 0 }
+      \bool_lazy_or:nnTF
+        { \sys_if_engine_xetex_p: } { \sys_if_engine_luatex_p: }
+        { \int_step_function:nN { 31 } \char_set_catcode_invalid:n }
+        { \int_step_function:nN { 31 } \char_set_catcode_active:n }
+      \int_step_function:nnN { 33 } { 64 } \char_set_catcode_other:n
+      \int_step_function:nnN { 65 } { 90 } \char_set_catcode_letter:n
+      \int_step_function:nnN { 91 } { 96 } \char_set_catcode_other:n
+      \int_step_function:nnN { 97 } { 122 } \char_set_catcode_letter:n
+      \char_set_catcode_ignore:n           { 9 }   % tab
+      \char_set_catcode_other:n            { 10 }  % lf
+      \char_set_catcode_active:n           { 12 }  % ff
+      \char_set_catcode_end_line:n         { 13 }  % cr
+      \char_set_catcode_ignore:n           { 32 }  % space
+      \char_set_catcode_parameter:n        { 35 }  % hash
+      \char_set_catcode_math_toggle:n      { 36 }  % dollar
+      \char_set_catcode_comment:n          { 37 }  % percent
+      \char_set_catcode_alignment:n        { 38 }  % ampersand
+      \char_set_catcode_letter:n           { 58 }  % colon
+      \char_set_catcode_escape:n           { 92 }  % backslash
+      \char_set_catcode_math_superscript:n { 94 }  % circumflex
+      \char_set_catcode_letter:n           { 95 }  % underscore
+      \char_set_catcode_group_begin:n      { 123 } % left brace
+      \char_set_catcode_other:n            { 124 } % pipe
+      \char_set_catcode_group_end:n        { 125 } % right brace
+      \char_set_catcode_space:n            { 126 } % tilde
+      \char_set_catcode_invalid:n          { 127 } % ^^?
+      \bool_lazy_or:nnF
+        { \sys_if_engine_xetex_p: } { \sys_if_engine_luatex_p: }
+        { \int_step_function:nnN { 128 } { 255 } \char_set_catcode_active:n }
+      \@@_gset:n { \c_code_cctab }
+    \group_end:
+    \cctab_const:Nn \c_document_cctab
+      {
+        \cctab_select:N \c_code_cctab
+        \int_set:Nn \tex_endlinechar:D { 13 }
+        \char_set_catcode_space:n          { 9 }
+        \char_set_catcode_space:n          { 32 }
+        \char_set_catcode_other:n          { 58 }
+        \char_set_catcode_math_subscript:n { 95 }
+        \char_set_catcode_active:n         { 126 }
+      }
+  }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_tmpa_cctab, \g_tmpb_cctab}
+%    \begin{macrocode}
+\cctab_new:N \g_tmpa_cctab
+\cctab_new:N \g_tmpb_cctab
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Messages}
+%
+%    \begin{macrocode}
+\msg_new:nnnn { cctab } { stack-full }
+  { The~category~code~table~stack~is~exhausted. }
+  {
+    LaTeX~has~been~asked~to~switch~to~a~new~category~code~table,~
+    but~there~is~no~more~space~to~do~this!
+  }
+\msg_new:nnnn { cctab } { extra-end }
+  { Extra~\iow_char:N\\cctab_end:~ignored~\msg_line_context:. }
+  {
+    LaTeX~came~across~a~\iow_char:N\\cctab_end:~without~a~matching~
+    \iow_char:N\\cctab_begin:N.~This~command~will~be~ignored.
+  }
+\msg_new:nnnn { cctab } { missing-end }
+  { Missing~\iow_char:N\\cctab_end:~before~end~of~TeX~run. }
+  {
+    LaTeX~came~across~more~\iow_char:N\\cctab_begin:N~than~
+    \iow_char:N\\cctab_end:.
+  }
+\msg_new:nnnn { cctab } { invalid-cctab }
+  { Invalid~\iow_char:N\\catcode~table. }
+  {
+    You~can~only~switch~to~a~\iow_char:N\\catcode~table~that~is~
+    initialized~using~\iow_char:N\\cctab_new:N~or~
+    \iow_char:N\\cctab_const:Nn.
+  }
+\msg_new:nnnn { cctab } { group-mismatch }
+  {
+    \iow_char:N\\cctab_end:~occurred~in~a~
+    \int_case:nn {#1}
+      {
+        { 0 } { different~group }
+        { 1 } { higher~group~level }
+        { -1 } { lower~group~level }
+      } ~than~
+    the~matching~\iow_char:N\\cctab_begin:N.
+  }
+  {
+    Catcode~tables~and~groups~must~be~properly~nested,~but~
+    you~tried~to~interleave~them.~LaTeX~will~try~to~proceed,~
+    but~results~may~be~unexpected.
+  }
+\prop_gput:Nnn \g_msg_module_name_prop { cctab } { LaTeX }
+\prop_gput:Nnn \g_msg_module_type_prop { cctab } { }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+%\PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3cctab.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3clist.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3clist.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3clist.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,2248 @@
+% \iffalse meta-comment
+%
+%% File: l3clist.dtx
+%
+% Copyright (C) 2004-2011 Frank Mittelbach, The LaTeX Project
+%           (C) 2012-2024 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 \pkg{l3clist} module\\ Comma separated lists^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% Comma lists (in short, |clist|) contain ordered data where items can
+% be added to the left or right end of the list.  This data type allows
+% basic list
+% manipulations such as adding/removing items, applying a function to
+% every item, removing duplicate items, extracting a given item, using
+% the comma list with specified separators, and so on.  Sequences
+% (defined in \pkg{l3seq}) are safer, faster, and provide more features,
+% so they should often be preferred to comma lists.  Comma lists are
+% mostly useful when interfacing with \LaTeXe{} or other code that
+% expects or provides items separated by commas.
+%
+% Several items can be added at once.  To ease input of comma lists from
+% data provided by a user outside an \cs{ExplSyntaxOn} \ldots{}
+% \cs{ExplSyntaxOff} block, spaces are removed from both sides of each
+% comma-delimited argument upon input.  Blank arguments are ignored, to
+% allow for trailing commas or repeated commas (which may otherwise
+% arise when concatenating comma lists \enquote{by hand}).  In addition,
+% a set of braces is removed if the result of space-trimming is braced:
+% this allows the storage of any item in a comma list.  For instance,
+% \begin{verbatim}
+%   \clist_new:N \l_my_clist
+%   \clist_put_left:Nn \l_my_clist { ~a~ , ~{b}~ , c~\d }
+%   \clist_put_right:Nn \l_my_clist { ~{e~} , , {{f}} , }
+% \end{verbatim}
+% results in |\l_my_clist| containing |a,b,c~\d,{e~},{{f}}| namely the
+% five items |a|, |b|, |c~\d|, |e~| and~|{f}|.  Comma lists normally do
+% not contain empty or blank items so the following gives an empty comma list:
+% \begin{verbatim}
+%   \clist_clear_new:N \l_my_clist
+%   \clist_set:Nn \l_my_clist { , ~ , , }
+%   \clist_if_empty:NTF \l_my_clist { true } { false }
+% \end{verbatim}
+% and it leaves \texttt{true} in the input stream.  To include an
+% \enquote{unsafe} item (empty, or one that contains a comma, or starts
+% or ends with a space, or is a single brace group), surround it with
+% braces.
+%
+% Any |n|-type token list is a valid comma list input for \pkg{l3clist}
+% functions, which will split the token list at every comma and process
+% the items as described above.  On the other hand, |N|-type functions
+% expect comma list variables, which are particular token list variables
+% in which this processing of items (and removal of blank items) has
+% already occurred.  Because comma list variables are token list
+% variables, expanding them once yields their items separated by commas,
+% and \pkg{l3tl} functions such as \cs{tl_show:N} can be applied to
+% them.  (These functions often have \pkg{l3clist} analogues, which
+% should be preferred.)
+%
+% Almost all operations on comma lists are
+% noticeably slower than those on sequences so converting the data to
+% sequences using \cs{seq_set_from_clist:Nn} (see \pkg{l3seq}) may be
+% advisable if speed is important.  The exception is that
+% \cs{clist_if_in:NnTF} and \cs{clist_remove_duplicates:N} may be faster
+% than their sequence analogues for large lists.  However, these
+% functions work slowly for \enquote{unsafe} items that must be braced,
+% and may produce errors when their argument contains |{|, |}| or |#|
+% (assuming the usual \TeX{} category codes apply).  The sequence
+% data type should thus certainly be preferred to comma lists to store
+% such items.
+%
+% \section{Creating and initialising comma lists}
+%
+% \begin{function}{\clist_new:N, \clist_new:c}
+%   \begin{syntax}
+%     \cs{clist_new:N} \meta{clist~var}
+%   \end{syntax}
+%   Creates a new \meta{clist~var} or raises an error if the name is
+%   already taken. The declaration is global. The \meta{clist~var}
+%   initially contains no items.
+% \end{function}
+%
+% \begin{function}[added = 2014-07-05]
+%   {
+%     \clist_const:Nn, \clist_const:Ne,
+%     \clist_const:cn, \clist_const:ce
+%   }
+%   \begin{syntax}
+%     \cs{clist_const:Nn} \meta{clist~var} \Arg{comma list}
+%   \end{syntax}
+%   Creates a new constant \meta{clist~var} or raises an error
+%   if the name is already taken. The value of the
+%   \meta{clist~var} is set globally to the
+%   \meta{comma list}.
+% \end{function}
+%
+% \begin{function}
+%   {\clist_clear:N, \clist_clear:c, \clist_gclear:N, \clist_gclear:c}
+%   \begin{syntax}
+%     \cs{clist_clear:N} \meta{clist~var}
+%   \end{syntax}
+%   Clears all items from the \meta{clist~var}.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \clist_clear_new:N,  \clist_clear_new:c,
+%     \clist_gclear_new:N, \clist_gclear_new:c
+%   }
+%   \begin{syntax}
+%     \cs{clist_clear_new:N} \meta{clist~var}
+%   \end{syntax}
+%   Ensures that the \meta{clist~var} exists globally by applying
+%   \cs{clist_new:N} if necessary, then applies
+%   \cs[index=clist_clear:N]{clist_(g)clear:N} to leave
+%   the list empty.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \clist_set_eq:NN,  \clist_set_eq:cN,
+%     \clist_set_eq:Nc,  \clist_set_eq:cc,
+%     \clist_gset_eq:NN, \clist_gset_eq:cN,
+%     \clist_gset_eq:Nc, \clist_gset_eq:cc
+%   }
+%   \begin{syntax}
+%     \cs{clist_set_eq:NN} \meta{clist~var_1} \meta{clist~var_2}
+%   \end{syntax}
+%   Sets the content of \meta{clist~var_1} equal to that of
+%   \meta{clist~var_2}.  To set a token list variable equal to a comma
+%   list variable, use \cs{tl_set_eq:NN}.  Conversely, setting a comma
+%   list variable to a token list is unadvisable unless one checks
+%   space-trimming and related issues.
+% \end{function}
+%
+% \begin{function}[added = 2014-07-17]
+%   {
+%     \clist_set_from_seq:NN,  \clist_set_from_seq:cN,
+%     \clist_set_from_seq:Nc,  \clist_set_from_seq:cc,
+%     \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
+%     \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
+%   }
+%   \begin{syntax}
+%     \cs{clist_set_from_seq:NN} \meta{clist~var} \meta{seq~var}
+%   \end{syntax}
+%   Converts the data in the \meta{seq~var} into a \meta{clist~var}:
+%   the original \meta{seq~var} is unchanged.
+%   Items which contain either spaces or commas are surrounded by braces.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \clist_concat:NNN,  \clist_concat:ccc,
+%     \clist_gconcat:NNN, \clist_gconcat:ccc
+%   }
+%   \begin{syntax}
+%     \cs{clist_concat:NNN} \meta{clist~var_1} \meta{clist~var_2} \meta{clist~var_3}
+%   \end{syntax}
+%   Concatenates the content of \meta{clist~var_2} and \meta{clist~var_3}
+%   together and saves the result in \meta{clist~var_1}. The items in
+%   \meta{clist~var_2} are placed at the left side of the new comma list.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added=2012-03-03]
+%   {\clist_if_exist:N, \clist_if_exist:c}
+%   \begin{syntax}
+%     \cs{clist_if_exist_p:N} \meta{clist~var}
+%     \cs{clist_if_exist:NTF} \meta{clist~var} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{clist~var} is currently defined.  This does
+%   not check that the \meta{clist~var} really is a comma list.
+% \end{function}
+%
+% \section{Adding data to comma lists}
+%
+% \begin{function}[added = 2011-09-06]
+%   {
+%     \clist_set:Nn,  \clist_set:NV, \clist_set:Ne,
+%     \clist_set:No,
+%     \clist_set:cn,  \clist_set:cV, \clist_set:ce,
+%     \clist_set:co,
+%     \clist_gset:Nn, \clist_gset:NV, \clist_gset:Ne,
+%     \clist_gset:No,
+%     \clist_gset:cn, \clist_gset:cV, \clist_gset:ce,
+%     \clist_gset:co
+%   }
+%   \begin{syntax}
+%     \cs{clist_set:Nn} \meta{clist~var} |{|\meta{item_1},\ldots{},\meta{item_n}|}|
+%   \end{syntax}
+%   Sets \meta{clist~var} to contain the \meta{items},
+%   removing any previous content from the variable.
+%   Blank items are omitted, spaces are removed from both sides of each
+%   item, then a set of braces is removed if the resulting space-trimmed
+%   item is braced.
+%   To store some \meta{tokens} as a single \meta{item} even if the
+%   \meta{tokens} contain commas or spaces, add a set of braces:
+%   \cs{clist_set:Nn} \meta{clist~var} |{| \Arg{tokens} |}|.
+% \end{function}
+%
+% \begin{function}[updated = 2011-09-05]
+%   {
+%     \clist_put_left:Nn,  \clist_put_left:NV,
+%     \clist_put_left:Nv,  \clist_put_left:Ne,
+%     \clist_put_left:No,
+%     \clist_put_left:cn,  \clist_put_left:cV,
+%     \clist_put_left:cv,  \clist_put_left:ce,
+%     \clist_put_left:co,
+%     \clist_gput_left:Nn, \clist_gput_left:NV,
+%     \clist_gput_left:Nv, \clist_gput_left:Ne,
+%     \clist_gput_left:No,
+%     \clist_gput_left:cn, \clist_gput_left:cV,
+%     \clist_gput_left:cv, \clist_gput_left:ce,
+%     \clist_gput_left:co
+%   }
+%   \begin{syntax}
+%     \cs{clist_put_left:Nn} \meta{clist~var} |{|\meta{item_1},\ldots{},\meta{item_n}|}|
+%   \end{syntax}
+%   Appends the \meta{items} to the left of the \meta{clist~var}.
+%   Blank items are omitted, spaces are removed from both sides of each
+%   item, then a set of braces is removed if the resulting space-trimmed
+%   item is braced.
+%   To append some \meta{tokens} as a single \meta{item} even if the
+%   \meta{tokens} contain commas or spaces, add a set of braces:
+%   \cs{clist_put_left:Nn} \meta{clist~var} |{| \Arg{tokens} |}|.
+% \end{function}
+%
+% \begin{function}[updated = 2011-09-05]
+%   {
+%     \clist_put_right:Nn,  \clist_put_right:NV,
+%     \clist_put_right:Nv,  \clist_put_right:Ne,
+%     \clist_put_right:No,
+%     \clist_put_right:cn,  \clist_put_right:cV,
+%     \clist_put_right:cv,  \clist_put_right:ce,
+%     \clist_put_right:co,
+%     \clist_gput_right:Nn, \clist_gput_right:NV,
+%     \clist_gput_right:Nv, \clist_gput_right:Ne,
+%     \clist_gput_right:No,
+%     \clist_gput_right:cn, \clist_gput_right:cV,
+%     \clist_gput_right:cv, \clist_gput_right:ce,
+%     \clist_gput_right:co
+%   }
+%   \begin{syntax}
+%     \cs{clist_put_right:Nn} \meta{clist~var} |{|\meta{item_1},\ldots{},\meta{item_n}|}|
+%   \end{syntax}
+%   Appends the \meta{items} to the right of the \meta{clist~var}.
+%   Blank items are omitted, spaces are removed from both sides of each
+%   item, then a set of braces is removed if the resulting space-trimmed
+%   item is braced.
+%   To append some \meta{tokens} as a single \meta{item} even if the
+%   \meta{tokens} contain commas or spaces, add a set of braces:
+%   \cs{clist_put_right:Nn} \meta{clist~var} |{| \Arg{tokens} |}|.
+% \end{function}
+%
+% \section{Modifying comma lists}
+%
+% While comma lists are normally used as ordered lists, it may be
+% necessary to modify the content. The functions here may be used
+% to update comma lists, while retaining the order of the unaffected
+% entries.
+%
+% \begin{function}
+%   {
+%     \clist_remove_duplicates:N,  \clist_remove_duplicates:c,
+%     \clist_gremove_duplicates:N, \clist_gremove_duplicates:c
+%   }
+%   \begin{syntax}
+%     \cs{clist_remove_duplicates:N} \meta{clist~var}
+%   \end{syntax}
+%   Removes duplicate items from the \meta{clist~var}, leaving the
+%   left most copy of each item in the \meta{clist~var}.  The \meta{item}
+%   comparison takes place on a token basis, as for \cs{tl_if_eq:nnTF}.
+%   \begin{texnote}
+%     This function iterates through every item in the \meta{clist~var} and
+%     does a comparison with the \meta{items} already checked. It is therefore
+%     relatively slow with large comma lists.
+%     Furthermore, it may fail if any of the items in the
+%     \meta{clist~var} contains |{|, |}|, or |#|
+%     (assuming the usual \TeX{} category codes apply).
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[updated = 2011-09-06]
+%   {
+%     \clist_remove_all:Nn,  \clist_remove_all:cn,
+%     \clist_remove_all:NV,  \clist_remove_all:cV,
+%     \clist_gremove_all:Nn, \clist_gremove_all:cn,
+%     \clist_gremove_all:NV, \clist_gremove_all:cV
+%   }
+%   \begin{syntax}
+%     \cs{clist_remove_all:Nn} \meta{clist~var} \Arg{item}
+%   \end{syntax}
+%   Removes every occurrence of \meta{item} from the \meta{clist~var}.
+%   The \meta{item} comparison takes place on a token basis, as for
+%   \cs{tl_if_eq:nnTF}.
+%   \begin{texnote}
+%     The function may fail if the \meta{item} contains |{|, |}|, or |#|
+%     (assuming the usual \TeX{} category codes apply).
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2014-07-18]
+%   {
+%     \clist_reverse:N, \clist_reverse:c,
+%     \clist_greverse:N, \clist_greverse:c
+%   }
+%   \begin{syntax}
+%     \cs{clist_reverse:N} \meta{clist~var}
+%   \end{syntax}
+%   Reverses the order of items stored in the \meta{clist~var}.
+% \end{function}
+%
+% \begin{function}[added = 2014-07-18]{\clist_reverse:n}
+%   \begin{syntax}
+%     \cs{clist_reverse:n} \Arg{comma list}
+%   \end{syntax}
+%   Leaves the items in the \meta{comma list} in the input stream in
+%   reverse order.  Contrarily to other what is done for other
+%   \texttt{n}-type \meta{comma list} arguments, braces and spaces are
+%   preserved by this process.
+%   \begin{texnote}
+%     The result is returned within \tn{unexpanded}, which means that the
+%     comma list does not expand further when appearing in an
+%     \texttt{e}-type or \texttt{x}-type argument expansion.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2017-02-06]
+%   {\clist_sort:Nn, \clist_sort:cn, \clist_gsort:Nn, \clist_gsort:cn}
+%   \begin{syntax}
+%     \cs{clist_sort:Nn} \meta{clist var} \Arg{comparison code}
+%   \end{syntax}
+%   Sorts the items in the \meta{clist var} according to the
+%   \meta{comparison code}, and assigns the result to
+%   \meta{clist var}. The details of sorting comparison are
+%   described in Section~\ref{sec:l3sort:mech}.
+% \end{function}
+%
+% \section{Comma list conditionals}
+%
+% \begin{function}[EXP,pTF]{\clist_if_empty:N, \clist_if_empty:c}
+%   \begin{syntax}
+%     \cs{clist_if_empty_p:N} \meta{clist~var}
+%     \cs{clist_if_empty:NTF} \meta{clist~var} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests if the \meta{clist~var} is empty (containing no items).
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2014-07-05]{\clist_if_empty:n}
+%   \begin{syntax}
+%     \cs{clist_if_empty_p:n} \Arg{comma list}
+%     \cs{clist_if_empty:nTF} \Arg{comma list} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests if the \meta{clist~var} is empty (containing no items).
+%   The rules for space trimming are as for other \texttt{n}-type
+%   comma-list functions, hence the comma list |{~,~,,~}| (without
+%   outer braces) is empty, while |{~,{},}| (without outer braces)
+%   contains one element, which happens to be empty: the comma-list
+%   is not empty.
+% \end{function}
+%
+% \begin{function}[updated = 2011-09-06, TF]
+%   {
+%      \clist_if_in:Nn, \clist_if_in:NV, \clist_if_in:No,
+%      \clist_if_in:cn, \clist_if_in:cV, \clist_if_in:co,
+%      \clist_if_in:nn, \clist_if_in:nV, \clist_if_in:no
+%   }
+%   \begin{syntax}
+%     \cs{clist_if_in:NnTF} \meta{clist~var} \Arg{item} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests if the \meta{item} is present in the \meta{clist~var}.
+%   In the case of an \texttt{n}-type \meta{comma list}, the usual rules
+%   of space trimming and brace stripping apply.  Hence,
+%   \begin{verbatim}
+%     \clist_if_in:nnTF { a , {b}~ , {b} , c } { b } {true} {false}
+%   \end{verbatim}
+%   yields \texttt{true}.
+%   \begin{texnote}
+%     The function may fail if the \meta{item} contains |{|, |}|, or |#|
+%     (assuming the usual \TeX{} category codes apply).
+%   \end{texnote}
+% \end{function}
+%
+% \section{Mapping over comma lists}
+%
+% The functions described in this section apply a specified function
+% to each item of a comma list.
+% All mappings are done at the current group level, \emph{i.e.}~any
+% local assignments made by the \meta{function} or \meta{code} discussed
+% below remain in effect after the loop.
+%
+% When the comma list is given explicitly, as an \texttt{n}-type argument,
+% spaces are trimmed around each item.
+% If the result of trimming spaces is empty, the item is ignored.
+% Otherwise, if the item is surrounded by braces, one set is removed,
+% and the result is passed to the mapped function. Thus, if the
+% comma list that is being mapped is \verb*|{a , {{b} }, ,{}, {c},}|
+% then the arguments passed to the mapped function are
+% `\verb*|a|', `\verb*|{b} |', an empty argument, and `\verb*|c|'.
+%
+% When the comma list is given as an \texttt{N}-type argument, spaces
+% have already been trimmed on input, and items are simply stripped
+% of one set of braces if any. This case is more efficient than using
+% \texttt{n}-type comma lists.
+%
+% \begin{function}[rEXP, updated = 2012-06-29]
+%   {\clist_map_function:NN, \clist_map_function:cN, \clist_map_function:nN, \clist_map_function:eN}
+%   \begin{syntax}
+%     \cs{clist_map_function:NN} \meta{clist~var} \meta{function}
+%   \end{syntax}
+%   Applies \meta{function} to every \meta{item} stored in the
+%   \meta{clist~var}. The \meta{function} receives one argument for
+%   each iteration. The \meta{items} are returned from left to right.
+%   The function \cs{clist_map_inline:Nn} is in general more efficient
+%   than \cs{clist_map_function:NN}.
+% \end{function}
+%
+% \begin{function}[updated = 2012-06-29]
+%   {\clist_map_inline:Nn, \clist_map_inline:cn, \clist_map_inline:nn}
+%   \begin{syntax}
+%     \cs{clist_map_inline:Nn} \meta{clist~var} \Arg{inline function}
+%   \end{syntax}
+%   Applies \meta{inline function} to every \meta{item} stored
+%   within the \meta{clist~var}. The \meta{inline function} should
+%   consist of code which receives the \meta{item} as |#1|.
+%   The \meta{items} are returned from left to right.
+% \end{function}
+%
+% \begin{function}[updated = 2012-06-29]
+%   {\clist_map_variable:NNn, \clist_map_variable:cNn, \clist_map_variable:nNn}
+%   \begin{syntax}
+%     \cs{clist_map_variable:NNn} \meta{clist~var} \meta{variable} \Arg{code}
+%   \end{syntax}
+%   Stores each \meta{item} of the \meta{clist~var} in turn in the
+%   (token list) \meta{variable} and applies the \meta{code}.  The
+%   \meta{code} will usually make use of the \meta{variable}, but this
+%   is not enforced.  The assignments to the \meta{variable} are local.
+%   Its value after the loop is the last \meta{item} in the \meta{clist~var},
+%   or its original value if there were no \meta{item}.  The
+%   \meta{items} are returned from left to right.
+% \end{function}
+%
+% \begin{function}[rEXP, added = 2021-05-05]
+%   {\clist_map_tokens:Nn, \clist_map_tokens:cn, \clist_map_tokens:nn}
+%   \begin{syntax}
+%     \cs{clist_map_tokens:Nn} \meta{clist~var} \Arg{code}
+%     \cs{clist_map_tokens:nn} \Arg{comma list} \Arg{code}
+%   \end{syntax}
+%   Calls \meta{code} \Arg{item} for every \meta{item} stored in the
+%   \meta{clist~var}. The \meta{code} receives each \meta{item} as a
+%   trailing brace group.  If the \meta{code} consists of a single
+%   function this is equivalent to \cs{clist_map_function:nN}.
+% \end{function}
+%
+% \begin{function}[rEXP, updated = 2012-06-29]{\clist_map_break:}
+%   \begin{syntax}
+%     \cs{clist_map_break:}
+%   \end{syntax}
+%   Used to terminate a \cs[no-index]{clist_map_\ldots{}} function before all
+%   entries in the \meta{comma list} have been processed. This
+%   normally takes place within a conditional statement, for example
+%   \begin{verbatim}
+%     \clist_map_inline:Nn \l_my_clist
+%       {
+%         \str_if_eq:nnTF { #1 } { bingo }
+%           { \clist_map_break: }
+%           {
+%             % Do something useful
+%           }
+%       }
+%   \end{verbatim}
+%   Use outside of a \cs[no-index]{clist_map_\ldots{}} scenario leads to low
+%   level \TeX{} errors.
+%   \begin{texnote}
+%     When the mapping is broken, additional tokens may be inserted
+%     before further items are taken
+%     from the input stream. This depends on the design of the mapping
+%     function.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[updated = 2012-06-29, rEXP]{\clist_map_break:n}
+%   \begin{syntax}
+%     \cs{clist_map_break:n} \Arg{code}
+%   \end{syntax}
+%   Used to terminate a \cs[no-index]{clist_map_\ldots{}} function before all
+%   entries in the \meta{comma list} have been processed, inserting
+%   the \meta{code} after the mapping has ended. This
+%   normally takes place within a conditional statement, for example
+%   \begin{verbatim}
+%     \clist_map_inline:Nn \l_my_clist
+%       {
+%         \str_if_eq:nnTF { #1 } { bingo }
+%           { \clist_map_break:n { <code> } }
+%           {
+%             % Do something useful
+%           }
+%       }
+%   \end{verbatim}
+%   Use outside of a \cs[no-index]{clist_map_\ldots{}} scenario leads to low
+%   level \TeX{} errors.
+%   \begin{texnote}
+%     When the mapping is broken, additional tokens may be inserted
+%     before the \meta{code} is
+%     inserted into the input stream.
+%     This depends on the design of the mapping function.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2012-07-13]
+%   {\clist_count:N, \clist_count:c, \clist_count:n, \clist_count:e}
+%   \begin{syntax}
+%     \cs{clist_count:N} \meta{clist~var}
+%   \end{syntax}
+%   Leaves the number of items in the \meta{clist~var} in the input
+%   stream as an \meta{integer denotation}. The total number of items
+%   in a \meta{clist~var} includes those which are duplicates,
+%   \emph{i.e.}~every item in a \meta{clist~var} is counted.
+% \end{function}
+%
+% \section{Using the content of comma lists directly}
+%
+% \begin{function}[EXP, added = 2013-05-26]{\clist_use:Nnnn, \clist_use:cnnn}
+%   \begin{syntax}
+%     \cs{clist_use:Nnnn} \meta{clist~var} \Arg{separator~between~two} \Arg{separator~between~more~than~two} \Arg{separator~between~final~two}
+%   \end{syntax}
+%   Places the contents of the \meta{clist~var} in the input stream,
+%   with the appropriate \meta{separator} between the items.  Namely, if
+%   the comma list has more than two items, the \meta{separator between
+%     more than two} is placed between each pair of items except the
+%   last, for which the \meta{separator between final two} is used.  If
+%   the comma list has exactly two items, then they are placed in the input
+%   stream separated by the \meta{separator between two}.  If the comma
+%   list has a single item, it is placed in the input stream, and a comma
+%   list with no items produces no output.  An error is raised if
+%   the variable does not exist or if it is invalid.
+%
+%   For example,
+%   \begin{verbatim}
+%     \clist_set:Nn \l_tmpa_clist { a , b , , c , {de} , f }
+%     \clist_use:Nnnn \l_tmpa_clist { ~and~ } { ,~ } { ,~and~ }
+%   \end{verbatim}
+%   inserts \enquote{\texttt{a, b, c, de, and f}} in the input
+%   stream.  The first separator argument is not used in this case
+%   because the comma list has more than $2$ items.
+%   \begin{texnote}
+%     The result is returned within the \tn{unexpanded}
+%     primitive (\cs{exp_not:n}), which means that the \meta{items}
+%     do not expand further when appearing in an \texttt{e}-type
+%     or \texttt{x}-type argument expansion.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2013-05-26]{\clist_use:Nn, \clist_use:cn}
+%   \begin{syntax}
+%     \cs{clist_use:Nn} \meta{clist~var} \Arg{separator}
+%   \end{syntax}
+%   Places the contents of the \meta{clist~var} in the input stream,
+%   with the \meta{separator} between the items. If the comma
+%   list has a single item, it is placed in the input stream, and a comma
+%   list with no items produces no output.  An error is raised if
+%   the variable does not exist or if it is invalid.
+%
+%   For example,
+%   \begin{verbatim}
+%     \clist_set:Nn \l_tmpa_clist { a , b , , c , {de} , f }
+%     \clist_use:Nn \l_tmpa_clist { ~and~ }
+%   \end{verbatim}
+%   inserts \enquote{\texttt{a and b and c and de and f}} in the input
+%   stream.
+%   \begin{texnote}
+%     The result is returned within the \tn{unexpanded}
+%     primitive (\cs{exp_not:n}), which means that the \meta{items}
+%     do not expand further when appearing in an \texttt{e}-type
+%     or \texttt{x}-type argument expansion.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2021-05-10]{\clist_use:nnnn, \clist_use:nn}
+%   \begin{syntax}
+%     \cs{clist_use:nnnn} \meta{comma~list} \Arg{separator~between~two} \Arg{separator~between~more~than~two} \Arg{separator~between~final~two}
+%     \cs{clist_use:nn} \meta{comma~list} \Arg{separator}
+%   \end{syntax}
+%   Places the contents of the \meta{comma~list} in the input stream,
+%   with the appropriate \meta{separator} between the items.  As for
+%   \cs{clist_set:Nn}, blank items are omitted, spaces are removed from
+%   both sides of each item, then a set of braces is removed if the
+%   resulting space-trimmed item is braced.  The \meta{separators} are
+%   then inserted in the same way as for \cs{clist_use:Nnnn} and
+%   \cs{clist_use:Nn}, respectively.
+%   \begin{texnote}
+%     The result is returned within the \tn{unexpanded}
+%     primitive (\cs{exp_not:n}), which means that the \meta{items}
+%     do not expand further when appearing in an \texttt{e}-type
+%     or \texttt{x}-type argument expansion.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Comma lists as stacks}
+%
+% Comma lists can be used as stacks, where data is pushed to and popped
+% from the top of the comma list. (The left of a comma list is the top, for
+% performance reasons.) The stack functions for comma lists are not
+% intended to be mixed with the general ordered data functions detailed
+% in the previous section: a comma list should either be used as an
+% ordered data type or as a stack, but not in both ways.
+%
+% \begin{function}[noTF, added = 2012-05-14, updated = 2019-02-16]
+%   {\clist_get:NN, \clist_get:cN}
+%   \begin{syntax}
+%     \cs{clist_get:NN} \meta{clist~var} \meta{token list variable}
+%   \end{syntax}
+%   Stores the left-most item from a \meta{clist~var} in the
+%   \meta{token list variable} without removing it from the
+%   \meta{clist~var}. The \meta{token list variable} is assigned locally.
+%   In the non-branching version, if the \meta{clist~var} is empty the
+%   \meta{token list variable} is set to the marker value \cs{q_no_value}.
+% \end{function}
+%
+% \begin{function}[updated = 2011-09-06]{\clist_pop:NN, \clist_pop:cN}
+%   \begin{syntax}
+%     \cs{clist_pop:NN} \meta{clist~var} \meta{token list variable}
+%   \end{syntax}
+%   Pops the left-most item from a \meta{clist~var} into the
+%   \meta{token list variable}, \emph{i.e.}~removes the item from the
+%   comma list and stores it in the \meta{token list variable}.
+%   Both of the variables are assigned locally.
+% \end{function}
+%
+% \begin{function}{\clist_gpop:NN, \clist_gpop:cN}
+%   \begin{syntax}
+%     \cs{clist_gpop:NN} \meta{clist~var} \meta{token list variable}
+%   \end{syntax}
+%   Pops the left-most item from a \meta{clist~var} into the
+%   \meta{token list variable}, \emph{i.e.}~removes the item from the
+%   comma list and stores it in the \meta{token list variable}.
+%   The \meta{clist~var} is modified globally, while the assignment of
+%   the \meta{token list variable} is local.
+% \end{function}
+%
+% \begin{function}[TF, added = 2012-05-14]{\clist_pop:NN, \clist_pop:cN}
+%   \begin{syntax}
+%     \cs{clist_pop:NNTF} \meta{clist~var} \meta{token list variable} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   If the \meta{clist~var} is empty, leaves the \meta{false code} in the
+%   input stream.  The value of the \meta{token list variable} is
+%   not defined in this case and should not be relied upon.  If the
+%   \meta{clist~var} is non-empty, pops the top item from the
+%   \meta{clist~var} in the \meta{token list variable}, \emph{i.e.}~removes
+%   the item from the \meta{clist~var}. Both the \meta{clist~var} and the
+%   \meta{token list variable} are assigned locally.
+% \end{function}
+%
+% \begin{function}[TF, added = 2012-05-14]{\clist_gpop:NN, \clist_gpop:cN}
+%   \begin{syntax}
+%     \cs{clist_gpop:NNTF} \meta{clist~var} \meta{token list variable} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   If the \meta{clist~var} is empty, leaves the \meta{false code} in the
+%   input stream.  The value of the \meta{token list variable} is
+%   not defined in this case and should not be relied upon.  If the
+%   \meta{clist~var} is non-empty, pops the top item from the
+%   \meta{clist~var} in the \meta{token list variable}, \emph{i.e.}~removes
+%   the item from the \meta{clist~var}. The \meta{clist~var} is modified
+%   globally, while the \meta{token list variable} is assigned locally.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \clist_push:Nn,  \clist_push:NV,  \clist_push:No,
+%     \clist_push:cn,  \clist_push:cV,  \clist_push:co,
+%     \clist_gpush:Nn, \clist_gpush:NV, \clist_gpush:No,
+%     \clist_gpush:cn, \clist_gpush:cV, \clist_gpush:co,
+%   }
+%   \begin{syntax}
+%     \cs{clist_push:Nn} \meta{clist~var} \Arg{items}
+%   \end{syntax}
+%   Adds the \Arg{items} to the top of the \meta{clist~var}.
+%   Spaces are removed from both sides of each item as for any
+%   \texttt{n}-type comma list.
+% \end{function}
+%
+% \section{Using a single item}
+%
+% \begin{function}[added = 2014-07-17, EXP]
+%   {\clist_item:Nn, \clist_item:cn, \clist_item:nn, \clist_item:en}
+%   \begin{syntax}
+%     \cs{clist_item:Nn} \meta{clist~var} \Arg{int expr}
+%   \end{syntax}
+%   Indexing items in the \meta{clist~var} from~$1$ at the top (left), this
+%   function evaluates the \meta{int expr} and leaves the
+%   appropriate item from the comma list in the input stream. If the
+%   \meta{int expr} is negative, indexing occurs from the
+%   bottom (right) of the comma list. When the \meta{int expr}
+%   is larger than the number of items in the \meta{clist~var} (as
+%   calculated by \cs{clist_count:N}) then the function expands to
+%   nothing.
+%   \begin{texnote}
+%     The result is returned within the \tn{unexpanded}
+%     primitive (\cs{exp_not:n}), which means that the \meta{item}
+%     does not expand further when appearing in an \texttt{e}-type
+%     or \texttt{x}-type argument expansion.
+%   \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2016-12-06]
+%   {\clist_rand_item:N, \clist_rand_item:n, \clist_rand_item:c}
+%   \begin{syntax}
+%     \cs{clist_rand_item:N} \meta{clist~var}
+%     \cs{clist_rand_item:n} \Arg{comma list}
+%   \end{syntax}
+%   Selects a pseudo-random item of the \meta{clist~var}/\meta{comma list}.
+%   If the \meta{comma list} has no item, the result is empty.
+%   \begin{texnote}
+%     The result is returned within the \tn{unexpanded}
+%     primitive (\cs{exp_not:n}), which means that the \meta{item}
+%     does not expand further when appearing in an \texttt{e}-type
+%     or \texttt{x}-type argument expansion.
+%   \end{texnote}
+% \end{function}
+%
+% \section{Viewing comma lists}
+%
+% \begin{function}[updated = 2021-04-29]{\clist_show:N, \clist_show:c}
+%   \begin{syntax}
+%     \cs{clist_show:N} \meta{clist~var}
+%   \end{syntax}
+%   Displays the entries in the \meta{clist~var} in the terminal.
+% \end{function}
+%
+% \begin{function}[updated = 2013-08-03]{\clist_show:n}
+%   \begin{syntax}
+%     \cs{clist_show:n} \Arg{tokens}
+%   \end{syntax}
+%   Displays the entries in the comma list in the terminal.
+% \end{function}
+%
+% \begin{function}[added = 2014-08-22, updated = 2021-04-29]{\clist_log:N, \clist_log:c}
+%   \begin{syntax}
+%     \cs{clist_log:N} \meta{clist~var}
+%   \end{syntax}
+%   Writes the entries in the \meta{clist~var} in the log file.  See
+%   also \cs{clist_show:N} which displays the result in the terminal.
+% \end{function}
+%
+% \begin{function}[added = 2014-08-22]{\clist_log:n}
+%   \begin{syntax}
+%     \cs{clist_log:n} \Arg{tokens}
+%   \end{syntax}
+%   Writes the entries in the comma list in the log file.  See also
+%   \cs{clist_show:n} which displays the result in the terminal.
+% \end{function}
+%
+% \section{Constant and scratch comma lists}
+%
+% \begin{variable}[added = 2012-07-02]{\c_empty_clist}
+%   Constant that is always empty.
+% \end{variable}
+%
+% \begin{variable}[added = 2011-09-06]{\l_tmpa_clist, \l_tmpb_clist}
+%   Scratch comma lists for local assignment. These are never used by
+%   the kernel code, and so are safe for use with any \LaTeX3-defined
+%   function. However, they may be overwritten by other non-kernel
+%   code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}[added = 2011-09-06]{\g_tmpa_clist, \g_tmpb_clist}
+%   Scratch comma lists for global assignment. These are never used by
+%   the kernel code, and so are safe for use with any \LaTeX3-defined
+%   function. However, they may be overwritten by other non-kernel
+%   code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3clist} implementation}
+%
+% \TestFiles{m3clist002}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=clist>
+%    \end{macrocode}
+%
+% \begin{variable}{\c_empty_clist}
+%   An empty comma list is simply an empty token list.
+%    \begin{macrocode}
+\cs_new_eq:NN \c_empty_clist \c_empty_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_internal_clist}
+%   Scratch space for various internal uses. This comma list variable
+%   cannot be declared as such because it comes before \cs{clist_new:N}
+%    \begin{macrocode}
+\tl_new:N \l_@@_internal_clist
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\s_@@_mark,\s_@@_stop}
+%   Internal scan marks.
+%    \begin{macrocode}
+\scan_new:N \s_@@_mark
+\scan_new:N \s_@@_stop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[EXP]{
+%     \@@_use_none_delimit_by_s_mark:w,
+%     \@@_use_none_delimit_by_s_stop:w,
+%     \@@_use_i_delimit_by_s_stop:nw
+%   }
+%   Functions to gobble up to a scan mark.
+%    \begin{macrocode}
+\cs_new:Npn \@@_use_none_delimit_by_s_mark:w #1 \s_@@_mark { }
+\cs_new:Npn \@@_use_none_delimit_by_s_stop:w #1 \s_@@_stop { }
+\cs_new:Npn \@@_use_i_delimit_by_s_stop:nw #1 #2 \s_@@_stop {#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_tmp:w}
+%   A temporary function for various purposes.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_tmp:w { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Removing spaces around items}
+%
+% \begin{macro}{\@@_trim_next:w}
+%   Called as \cs{exp:w} \cs{@@_trim_next:w} \cs{prg_do_nothing:}
+%   \meta{comma list} \ldots{} it expands to \Arg{trimmed item} where
+%   the \meta{trimmed item} is the first non-empty result from removing
+%   spaces from both ends of comma-delimited items in the \meta{comma
+%   list}.  The \cs{prg_do_nothing:} marker avoids losing braces.  The
+%   test for blank items is a somewhat optimized \cs{tl_if_empty:oTF}
+%   construction; if blank, another item is sought, otherwise trim
+%   spaces.
+%    \begin{macrocode}
+\cs_new:Npn \@@_trim_next:w #1 ,
+  {
+    \tl_if_empty:oTF { \use_none:nn #1 ? }
+      { \@@_trim_next:w \prg_do_nothing: }
+      { \tl_trim_spaces_apply:oN {#1} \exp_end: }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[rEXP]{\@@_sanitize:n}
+% \begin{macro}{\@@_sanitize:Nn}
+%   The auxiliary \cs{@@_sanitize:Nn} receives a delimiter
+%   (\cs{c_empty_tl} the first time, afterwards a comma) and that item
+%   as arguments.  Unless we are done with the loop it calls
+%   \cs{@@_wrap_item:w} to unbrace the item (using a comma delimiter is
+%   safe since |#2| came from removing spaces from an argument delimited
+%   by a comma) and possibly re-brace it if needed.
+%    \begin{macrocode}
+\cs_new:Npn \@@_sanitize:n #1
+  {
+    \exp_after:wN \@@_sanitize:Nn \exp_after:wN \c_empty_tl
+    \exp:w \@@_trim_next:w \prg_do_nothing:
+    #1 , \s_@@_stop \prg_break: , \prg_break_point:
+  }
+\cs_new:Npn \@@_sanitize:Nn #1#2
+  {
+    \@@_use_none_delimit_by_s_stop:w #2 \s_@@_stop
+    #1 \@@_wrap_item:w #2 ,
+    \exp_after:wN \@@_sanitize:Nn \exp_after:wN ,
+    \exp:w \@@_trim_next:w \prg_do_nothing:
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[TF]{\@@_if_wrap:n}
+% \begin{macro}{\@@_if_wrap:w}
+%   True if the argument must be wrapped to avoid getting altered by some
+%   clist operations.  That is the case whenever the argument
+%   \begin{itemize}
+%   \item starts or end with a space or contains a comma,
+%   \item is empty, or
+%   \item consists of a single braced group.
+%   \end{itemize}
+%   If the argument starts or ends with a space or contains
+%   a comma then one of the three arguments of \cs{@@_if_wrap:w} will
+%   have its end delimiter (partly) in one of the three copies of |#1|
+%   in \cs{@@_if_wrap:nTF}; this has a knock-on effect meaning that the
+%   result of the expansion is not empty; in that case, wrap.
+%   Otherwise, the argument is safe unless it starts with a brace group
+%   (or is empty) and it is empty or consists of a single
+%   \texttt{n}-type argument.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_wrap:n #1 { TF }
+  {
+    \tl_if_empty:oTF
+      {
+        \@@_if_wrap:w
+          \s_@@_mark ? #1 ~ \s_@@_mark ? ~ #1
+          \s_@@_mark , ~ \s_@@_mark #1 ,
+      }
+      {
+        \tl_if_head_is_group:nTF { #1 { } }
+          {
+            \tl_if_empty:nTF {#1}
+              { \prg_return_true: }
+              {
+                \tl_if_empty:oTF { \use_none:n #1}
+                  { \prg_return_true: }
+                  { \prg_return_false: }
+              }
+          }
+          { \prg_return_false: }
+      }
+      { \prg_return_true: }
+  }
+\cs_new:Npn \@@_if_wrap:w #1 \s_@@_mark ? ~ #2 ~ \s_@@_mark #3 , { }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_wrap_item:w}
+%   Safe items are put in \cs{exp_not:n}, otherwise we put an extra set
+%   of braces.
+%    \begin{macrocode}
+\cs_new:Npn \@@_wrap_item:w #1 ,
+  { \@@_if_wrap:nTF {#1} { \exp_not:n { {#1} } } { \exp_not:n {#1} } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Allocation and initialisation}
+%
+% \begin{macro}{\clist_new:N, \clist_new:c}
+% \UnitTested
+%   Internally, comma lists are just token lists.
+%    \begin{macrocode}
+\cs_new_eq:NN \clist_new:N \tl_new:N
+\cs_new_eq:NN \clist_new:c \tl_new:c
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \clist_const:Nn, \clist_const:Ne, \clist_const:Nx,
+%     \clist_const:cn, \clist_const:ce, \clist_const:cx
+%   }
+%   Creating and initializing a constant comma list is done by
+%   sanitizing all items (stripping spaces and braces).
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_const:Nn #1#2
+  { \tl_const:Ne #1 { \@@_sanitize:n {#2} } }
+\cs_generate_variant:Nn \clist_const:Nn { Ne , c , ce }
+\cs_generate_variant:Nn \clist_const:Nn { Nx , cx }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\clist_clear:N, \clist_clear:c}
+% \UnitTested
+% \begin{macro}{\clist_gclear:N, \clist_gclear:c}
+% \UnitTested
+%   Clearing comma lists is just the same as clearing token lists.
+%    \begin{macrocode}
+\cs_new_eq:NN \clist_clear:N  \tl_clear:N
+\cs_new_eq:NN \clist_clear:c  \tl_clear:c
+\cs_new_eq:NN \clist_gclear:N \tl_gclear:N
+\cs_new_eq:NN \clist_gclear:c \tl_gclear:c
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_clear_new:N, \clist_clear_new:c}
+% \UnitTested
+% \begin{macro}{\clist_gclear_new:N, \clist_gclear_new:c}
+% \UnitTested
+%   Once again a copy from the token list functions.
+%    \begin{macrocode}
+\cs_new_eq:NN \clist_clear_new:N  \tl_clear_new:N
+\cs_new_eq:NN \clist_clear_new:c  \tl_clear_new:c
+\cs_new_eq:NN \clist_gclear_new:N \tl_gclear_new:N
+\cs_new_eq:NN \clist_gclear_new:c \tl_gclear_new:c
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {\clist_set_eq:NN, \clist_set_eq:cN, \clist_set_eq:Nc, \clist_set_eq:cc}
+% \UnitTested
+% \begin{macro}
+%   {
+%     \clist_gset_eq:NN, \clist_gset_eq:cN,
+%     \clist_gset_eq:Nc, \clist_gset_eq:cc
+%   }
+% \UnitTested
+%   Once again, these are simple copies from the token list functions.
+%    \begin{macrocode}
+\cs_new_eq:NN \clist_set_eq:NN  \tl_set_eq:NN
+\cs_new_eq:NN \clist_set_eq:Nc  \tl_set_eq:Nc
+\cs_new_eq:NN \clist_set_eq:cN  \tl_set_eq:cN
+\cs_new_eq:NN \clist_set_eq:cc  \tl_set_eq:cc
+\cs_new_eq:NN \clist_gset_eq:NN \tl_gset_eq:NN
+\cs_new_eq:NN \clist_gset_eq:Nc \tl_gset_eq:Nc
+\cs_new_eq:NN \clist_gset_eq:cN \tl_gset_eq:cN
+\cs_new_eq:NN \clist_gset_eq:cc \tl_gset_eq:cc
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \clist_set_from_seq:NN, \clist_set_from_seq:cN,
+%     \clist_set_from_seq:Nc, \clist_set_from_seq:cc
+%   }
+% \UnitTested
+% \begin{macro}
+%   {
+%     \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
+%     \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
+%   }
+% \UnitTested
+% \begin{macro}{\@@_set_from_seq:NNNN, \@@_set_from_seq:n}
+%   Setting a comma list from a comma-separated list is done using a
+%   simple mapping.  Safe items are put in \cs{exp_not:n}, otherwise we
+%   put an extra set of braces.  The first comma must be removed, except
+%   in the case of an empty comma-list.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_set_from_seq:NN
+  { \@@_set_from_seq:NNNN \clist_clear:N  \__kernel_tl_set:Nx  }
+\cs_new_protected:Npn \clist_gset_from_seq:NN
+  { \@@_set_from_seq:NNNN \clist_gclear:N \__kernel_tl_gset:Nx }
+\cs_new_protected:Npn \@@_set_from_seq:NNNN #1#2#3#4
+  {
+    \seq_if_empty:NTF #4
+      { #1 #3 }
+      {
+        #2 #3
+          {
+            \exp_after:wN \use_none:n \exp:w \exp_end_continue_f:w
+            \seq_map_function:NN #4 \@@_set_from_seq:n
+          }
+      }
+  }
+\cs_new:Npn \@@_set_from_seq:n #1
+  {
+    ,
+    \@@_if_wrap:nTF {#1}
+      { \exp_not:n { {#1} } }
+      { \exp_not:n {#1} }
+  }
+\cs_generate_variant:Nn \clist_set_from_seq:NN  {     Nc }
+\cs_generate_variant:Nn \clist_set_from_seq:NN  { c , cc }
+\cs_generate_variant:Nn \clist_gset_from_seq:NN {     Nc }
+\cs_generate_variant:Nn \clist_gset_from_seq:NN { c , cc }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_concat:NNN, \clist_concat:ccc}
+% \UnitTested
+% \begin{macro}{\clist_gconcat:NNN, \clist_gconcat:ccc}
+% \UnitTested
+% \begin{macro}{\@@_concat:NNNN}
+%   Concatenating comma lists is not quite as easy as it seems, as
+%   there needs to be the correct addition of a comma to the output. So
+%   a little work to do.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_concat:NNN
+  { \@@_concat:NNNN \__kernel_tl_set:Nx }
+\cs_new_protected:Npn \clist_gconcat:NNN
+  { \@@_concat:NNNN \__kernel_tl_gset:Nx }
+\cs_new_protected:Npn \@@_concat:NNNN #1#2#3#4
+  {
+    #1 #2
+      {
+        \exp_not:o #3
+        \clist_if_empty:NF #3 { \clist_if_empty:NF #4 { , } }
+        \exp_not:o #4
+      }
+  }
+\cs_generate_variant:Nn \clist_concat:NNN  { ccc }
+\cs_generate_variant:Nn \clist_gconcat:NNN { ccc }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\clist_if_exist:N, \clist_if_exist:c}
+%   Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
+%    \begin{macrocode}
+\prg_new_eq_conditional:NNn \clist_if_exist:N \cs_if_exist:N
+  { TF , T , F , p }
+\prg_new_eq_conditional:NNn \clist_if_exist:c \cs_if_exist:c
+  { TF , T , F , p }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Adding data to comma lists}
+%
+% \begin{macro}
+%   {
+%     \clist_set:Nn,  \clist_set:NV, \clist_set:Ne,
+%     \clist_set:No,  \clist_set:Nx,
+%     \clist_set:cn,  \clist_set:cV, \clist_set:ce,
+%     \clist_set:co,  \clist_set:cx
+%   }
+% \begin{macro}
+%   {
+%     \clist_gset:Nn, \clist_gset:NV, \clist_gset:Ne,
+%     \clist_gset:No, \clist_gset:Nx,
+%     \clist_gset:cn, \clist_gset:cV, \clist_gset:ce,
+%     \clist_gset:co, \clist_gset:cx,
+%   }
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_set:Nn #1#2
+  { \__kernel_tl_set:Nx #1 { \@@_sanitize:n {#2} } }
+\cs_new_protected:Npn \clist_gset:Nn #1#2
+  { \__kernel_tl_gset:Nx #1 { \@@_sanitize:n {#2} } }
+\cs_generate_variant:Nn \clist_set:Nn  { NV , Ne , c , cV , ce }
+\cs_generate_variant:Nn \clist_set:Nn  { No , Nx , co , cx }
+\cs_generate_variant:Nn \clist_gset:Nn { NV , Ne , c , cV , ce }
+\cs_generate_variant:Nn \clist_gset:Nn { No , Nx , co , cx }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \clist_put_left:Nn,  \clist_put_left:NV,
+%     \clist_put_left:Nv,  \clist_put_left:Ne,
+%     \clist_put_left:No,  \clist_put_left:Nx,
+%     \clist_put_left:cn,  \clist_put_left:cV,
+%     \clist_put_left:cv,  \clist_put_left:ce,
+%     \clist_put_left:co,  \clist_put_left:cx,
+%   }
+% \UnitTested
+% \begin{macro}
+%   {
+%     \clist_gput_left:Nn, \clist_gput_left:NV,
+%     \clist_gput_left:Nv, \clist_gput_left:Ne,
+%     \clist_gput_left:No, \clist_gput_left:Nx,
+%     \clist_gput_left:cn, \clist_gput_left:cV,
+%     \clist_gput_left:cv, \clist_gput_left:ce,
+%     \clist_gput_left:co, \clist_gput_left:cx,
+%   }
+% \UnitTested
+% \begin{macro}{\@@_put_left:NNNn}
+%   Everything is based on concatenation after storing in
+%   \cs{l_@@_internal_clist}.  This avoids having to worry here about
+%   space-trimming and so on.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_put_left:Nn
+  { \@@_put_left:NNNn \clist_concat:NNN \clist_set:Nn }
+\cs_new_protected:Npn \clist_gput_left:Nn
+  { \@@_put_left:NNNn \clist_gconcat:NNN \clist_set:Nn }
+\cs_new_protected:Npn \@@_put_left:NNNn #1#2#3#4
+  {
+    #2 \l_@@_internal_clist {#4}
+    #1 #3 \l_@@_internal_clist #3
+  }
+\cs_generate_variant:Nn \clist_put_left:Nn  { NV , Nv , Ne , c , cV , cv , ce }
+\cs_generate_variant:Nn \clist_put_left:Nn  { No , Nx , co , cx }
+\cs_generate_variant:Nn \clist_gput_left:Nn { NV , Nv , Ne , c , cV , cv , ce }
+\cs_generate_variant:Nn \clist_gput_left:Nn { No , Nx , co , cx }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \clist_put_right:Nn, \clist_put_right:NV,
+%     \clist_put_right:Nv, \clist_put_right:Ne,
+%     \clist_put_right:No, \clist_put_right:Nx,
+%     \clist_put_right:cn, \clist_put_right:cV,
+%     \clist_put_right:cv, \clist_put_right:ce,
+%     \clist_put_right:co, \clist_put_right:cx
+%   }
+% \UnitTested
+% \begin{macro}
+%   {
+%     \clist_gput_right:Nn, \clist_gput_right:NV,
+%     \clist_gput_right:Nv, \clist_gput_right:Ne,
+%     \clist_gput_right:No, \clist_gput_right:Nx,
+%     \clist_gput_right:cn, \clist_gput_right:cV,
+%     \clist_gput_right:cv, \clist_gput_right:ce,
+%     \clist_gput_right:cx, \clist_gput_right:co
+%   }
+% \UnitTested
+% \begin{macro}{\@@_put_right:NNNn}
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_put_right:Nn
+  { \@@_put_right:NNNn \clist_concat:NNN \clist_set:Nn }
+\cs_new_protected:Npn \clist_gput_right:Nn
+  { \@@_put_right:NNNn \clist_gconcat:NNN \clist_set:Nn }
+\cs_new_protected:Npn \@@_put_right:NNNn #1#2#3#4
+  {
+    #2 \l_@@_internal_clist {#4}
+    #1 #3 #3 \l_@@_internal_clist
+  }
+\cs_generate_variant:Nn \clist_put_right:Nn
+  { NV , Nv , Ne , c , cV , cv , ce }
+\cs_generate_variant:Nn \clist_put_right:Nn
+  { No , Nx , co , cx }
+\cs_generate_variant:Nn \clist_gput_right:Nn
+  { NV , Nv , Ne , c , cV , cv , ce }
+\cs_generate_variant:Nn \clist_gput_right:Nn
+  { No , Nx , co , cx }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Comma lists as stacks}
+%
+% \begin{macro}{\clist_get:NN, \clist_get:cN}
+% \UnitTested
+% \begin{macro}{\@@_get:wN}
+%   Getting an item from the left of a comma list is pretty easy: just
+%   trim off the first item using the comma.  No need to trim spaces as
+%   comma-list \emph{variables} are assumed to have \enquote{cleaned-up}
+%   items.  (Note that grabbing a comma-delimited item removes an outer
+%   pair of braces if present, exactly as needed to uncover the
+%   underlying item.)
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_get:NN #1#2
+  {
+    \if_meaning:w #1 \c_empty_clist
+      \tl_set:Nn #2 { \q_no_value }
+    \else:
+      \exp_after:wN \@@_get:wN #1 , \s_@@_stop #2
+    \fi:
+  }
+\cs_new_protected:Npn \@@_get:wN #1 , #2 \s_@@_stop #3
+  { \tl_set:Nn #3 {#1} }
+\cs_generate_variant:Nn \clist_get:NN { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_pop:NN, \clist_pop:cN}
+% \UnitTested
+% \begin{macro}{\clist_gpop:NN, \clist_gpop:cN}
+% \UnitTested
+% \begin{macro}
+%   {\@@_pop:NNN, \@@_pop:wwNNN, \@@_pop:wN}
+%   An empty clist leads to \cs{q_no_value}, otherwise grab until the
+%   first comma and assign to the variable.  The second argument of
+%   \cs{@@_pop:wwNNN} is a comma list ending in a comma and
+%   \cs{s_@@_mark}, unless the original clist contained exactly one item:
+%   then the argument is just \cs{s_@@_mark}.  The next auxiliary picks
+%   either \cs{exp_not:n} or \cs{use_none:n} as |#2|, ensuring that the
+%   result can safely be an empty comma list.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_pop:NN
+  { \@@_pop:NNN \__kernel_tl_set:Nx }
+\cs_new_protected:Npn \clist_gpop:NN
+  { \@@_pop:NNN \__kernel_tl_gset:Nx }
+\cs_new_protected:Npn \@@_pop:NNN #1#2#3
+  {
+    \if_meaning:w #2 \c_empty_clist
+      \tl_set:Nn #3 { \q_no_value }
+    \else:
+      \exp_after:wN \@@_pop:wwNNN #2 , \s_@@_mark \s_@@_stop #1#2#3
+    \fi:
+  }
+\cs_new_protected:Npn \@@_pop:wwNNN #1 , #2 \s_@@_stop #3#4#5
+  {
+    \tl_set:Nn #5 {#1}
+    #3 #4
+      {
+        \@@_pop:wN \prg_do_nothing:
+          #2 \exp_not:o
+          , \s_@@_mark \use_none:n
+        \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_pop:wN #1 , \s_@@_mark #2 #3 \s_@@_stop { #2 {#1} }
+\cs_generate_variant:Nn \clist_pop:NN  { c }
+\cs_generate_variant:Nn \clist_gpop:NN { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[TF]{\clist_get:NN, \clist_get:cN}
+% \begin{macro}[TF]{\clist_pop:NN, \clist_pop:cN}
+% \begin{macro}[TF]{\clist_gpop:NN, \clist_gpop:cN}
+% \begin{macro}{\@@_pop_TF:NNN}
+%   The same, as branching code: very similar to the above.
+%    \begin{macrocode}
+\prg_new_protected_conditional:Npnn \clist_get:NN #1#2 { T , F , TF }
+  {
+    \if_meaning:w #1 \c_empty_clist
+      \prg_return_false:
+    \else:
+      \exp_after:wN \@@_get:wN #1 , \s_@@_stop #2
+      \prg_return_true:
+    \fi:
+  }
+\prg_generate_conditional_variant:Nnn \clist_get:NN { c } { T , F , TF }
+\prg_new_protected_conditional:Npnn \clist_pop:NN #1#2 { T , F , TF }
+  { \@@_pop_TF:NNN \__kernel_tl_set:Nx #1 #2 }
+\prg_new_protected_conditional:Npnn \clist_gpop:NN #1#2 { T , F , TF }
+  { \@@_pop_TF:NNN \__kernel_tl_gset:Nx #1 #2 }
+\cs_new_protected:Npn \@@_pop_TF:NNN #1#2#3
+  {
+    \if_meaning:w #2 \c_empty_clist
+      \prg_return_false:
+    \else:
+      \exp_after:wN \@@_pop:wwNNN #2 , \s_@@_mark \s_@@_stop #1#2#3
+      \prg_return_true:
+    \fi:
+  }
+\prg_generate_conditional_variant:Nnn \clist_pop:NN { c } { T , F , TF }
+\prg_generate_conditional_variant:Nnn \clist_gpop:NN { c } { T , F , TF }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{
+%   \clist_push:Nn, \clist_push:NV, \clist_push:No, \clist_push:Nx,
+%   \clist_push:cn, \clist_push:cV, \clist_push:co, \clist_push:cx,
+% }
+% \UnitTested
+% \begin{macro}{
+%   \clist_gpush:Nn, \clist_gpush:NV, \clist_gpush:No, \clist_gpush:Nx,
+%   \clist_gpush:cn, \clist_gpush:cV, \clist_gpush:co, \clist_gpush:cx,
+% }
+% \UnitTested
+%   Pushing to a comma list is the same as adding on the left.
+%    \begin{macrocode}
+\cs_new_eq:NN \clist_push:Nn  \clist_put_left:Nn
+\cs_generate_variant:Nn \clist_push:Nn { NV , No , Nx , c , cV , co , cx }
+\cs_new_eq:NN \clist_gpush:Nn \clist_gput_left:Nn
+\cs_generate_variant:Nn \clist_gpush:Nn { NV , No , Nx , c , cV , co , cx }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Modifying comma lists}
+%
+% \begin{variable}{\l_@@_internal_remove_clist, \l_@@_internal_remove_seq}
+%   An internal comma list and a sequence for the removal routines.
+%    \begin{macrocode}
+\clist_new:N \l_@@_internal_remove_clist
+\seq_new:N \l_@@_internal_remove_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\clist_remove_duplicates:N, \clist_remove_duplicates:c}
+% \UnitTested
+% \begin{macro}{\clist_gremove_duplicates:N, \clist_gremove_duplicates:c}
+% \UnitTested
+% \begin{macro}{\@@_remove_duplicates:NN}
+%   Removing duplicates means making a new list then copying it.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_remove_duplicates:N
+  { \@@_remove_duplicates:NN \clist_set_eq:NN }
+\cs_new_protected:Npn \clist_gremove_duplicates:N
+  { \@@_remove_duplicates:NN \clist_gset_eq:NN }
+\cs_new_protected:Npn \@@_remove_duplicates:NN #1#2
+  {
+    \clist_clear:N \l_@@_internal_remove_clist
+    \clist_map_inline:Nn #2
+      {
+        \clist_if_in:NnF \l_@@_internal_remove_clist {##1}
+          {
+            \tl_put_right:Ne \l_@@_internal_remove_clist
+              {
+                \clist_if_empty:NF \l_@@_internal_remove_clist { , }
+                \@@_if_wrap:nTF {##1} { \exp_not:n { {##1} } } { \exp_not:n {##1} }
+              }
+          }
+      }
+    #1 #2 \l_@@_internal_remove_clist
+  }
+\cs_generate_variant:Nn \clist_remove_duplicates:N  { c }
+\cs_generate_variant:Nn \clist_gremove_duplicates:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \clist_remove_all:Nn, \clist_remove_all:cn,
+%     \clist_remove_all:NV, \clist_remove_all:cV
+%   }
+% \UnitTested
+% \begin{macro}
+%   {
+%     \clist_gremove_all:Nn, \clist_gremove_all:cn,
+%     \clist_gremove_all:NV, \clist_gremove_all:cV
+%   }
+% \UnitTested
+% \begin{macro}{\@@_remove_all:NNNn}
+% \begin{macro}{\@@_remove_all:w}
+% \begin{macro}{\@@_remove_all:}
+%   The method used here for safe items is very similar to
+%   \cs{tl_replace_all:Nnn}.  However, if the item contains commas or
+%   leading/trailing spaces, or is empty, or consists of a single brace
+%   group, we know that it can only appear within braces so the code
+%   would fail; instead just convert to a sequence and do the removal
+%   with \pkg{l3seq} code (it involves somewhat elaborate code to do
+%   most of the work expandably but the final token list comparisons
+%   non-expandably).
+%
+%   For \enquote{safe} items, build a function delimited by the
+%   \meta{item} that should be removed,
+%   surrounded with commas, and call that function followed by
+%   the expanded comma list, and another copy of the \meta{item}.
+%   The loop is controlled by the argument grabbed by
+%   \cs{@@_remove_all:w}: when the item was found,
+%   the \cs{s_@@_mark} delimiter used is the one inserted by
+%   \cs{@@_tmp:w}, and \cs{@@_use_none_delimit_by_s_stop:w}
+%   is deleted. At the end, the final \meta{item} is
+%   grabbed, and the argument of \cs{@@_tmp:w} contains
+%   \cs{s_@@_mark}: in that case, \cs{@@_remove_all:w}
+%   removes the second \cs{s_@@_mark} (inserted by \cs{@@_tmp:w}),
+%   and lets \cs{@@_use_none_delimit_by_s_stop:w} act.
+%
+%   No brace is lost because items are always grabbed with a leading comma.
+%   The result of the first assignment has an extra leading comma,
+%   which we remove in a second assignment.
+%   Two exceptions: if the clist lost all of its elements, the result
+%   is empty, and we shouldn't remove anything; if the clist started up
+%   empty, the first step happens to turn it into a single comma, and
+%   the second step removes it.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_remove_all:Nn
+  { \@@_remove_all:NNNn \clist_set_from_seq:NN \__kernel_tl_set:Nx }
+\cs_new_protected:Npn \clist_gremove_all:Nn
+  { \@@_remove_all:NNNn \clist_gset_from_seq:NN \__kernel_tl_gset:Nx }
+\cs_new_protected:Npn \@@_remove_all:NNNn #1#2#3#4
+  {
+    \@@_if_wrap:nTF {#4}
+      {
+        \seq_set_from_clist:NN \l_@@_internal_remove_seq #3
+        \seq_remove_all:Nn \l_@@_internal_remove_seq {#4}
+        #1 #3 \l_@@_internal_remove_seq
+      }
+      {
+        \cs_set:Npn \@@_tmp:w ##1 , #4 ,
+          {
+            ##1
+            , \s_@@_mark , \@@_use_none_delimit_by_s_stop:w ,
+            \@@_remove_all:
+          }
+        #2 #3
+          {
+            \exp_after:wN \@@_remove_all:
+            #3 , \s_@@_mark , #4 , \s_@@_stop
+          }
+        \clist_if_empty:NF #3
+          {
+            #2 #3
+              {
+                \exp_args:No \exp_not:o
+                  { \exp_after:wN \use_none:n #3 }
+              }
+          }
+      }
+  }
+\cs_new:Npn \@@_remove_all:
+  { \exp_after:wN \@@_remove_all:w \@@_tmp:w , }
+\cs_new:Npn \@@_remove_all:w #1 , \s_@@_mark , #2 , { \exp_not:n {#1} }
+\cs_generate_variant:Nn \clist_remove_all:Nn  { c , NV , cV }
+\cs_generate_variant:Nn \clist_gremove_all:Nn { c , NV , cV }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \clist_reverse:N, \clist_reverse:c,
+%     \clist_greverse:N, \clist_greverse:c
+%   }
+%   Use \cs{clist_reverse:n} in an \texttt{e}-expanding assignment.  The
+%   extra work that \cs{clist_reverse:n} does to preserve braces and
+%   spaces would not be needed for the well-controlled case of
+%   \texttt{N}-type comma lists, but the slow-down is not too bad.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_reverse:N #1
+  { \__kernel_tl_set:Nx #1 { \exp_args:No \clist_reverse:n {#1} } }
+\cs_new_protected:Npn \clist_greverse:N #1
+  { \__kernel_tl_gset:Nx #1 { \exp_args:No \clist_reverse:n {#1} } }
+\cs_generate_variant:Nn \clist_reverse:N { c }
+\cs_generate_variant:Nn \clist_greverse:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\clist_reverse:n}
+% \begin{macro}[EXP]{\@@_reverse:wwNww, \@@_reverse_end:ww}
+%   The reversed token list is built one item at a time, and stored
+%   between \cs{s_@@_stop} and \cs{s_@@_mark}, in the form of |?| followed by
+%   zero or more instances of \enquote{\meta{item}\texttt{,}}.  We start from a comma
+%   list \enquote{\meta{item_1}\texttt{,\ldots,}\meta{item_n}}.  During the loop,
+%   the auxiliary \cs{@@_reverse:wwNww} receives \enquote{\texttt{?}\meta{item_i}} as
+%   |#1|, \enquote{\meta{item_{i+1}}\texttt{,\ldots,}\meta{item_n}} as |#2|,
+%   \cs{@@_reverse:wwNww} as |#3|, what remains until \cs{s_@@_stop} as
+%   |#4|, and \enquote{\meta{item_{i-1}}\texttt{,\ldots,}\meta{item_1}\texttt{,}} as |#5|.
+%   The auxiliary moves |#1| just before |#5|, with a comma, and calls
+%   itself (|#3|).  After the last item is moved, \cs{@@_reverse:wwNww}
+%   receives \enquote{\cs{s_@@_mark} \cs{@@_reverse:wwNww} \texttt{!}} as its argument
+%   |#1|, thus \cs{@@_reverse_end:ww} as its argument |#3|.  This second
+%   auxiliary cleans up until the marker~|!|, removes the trailing comma
+%   (introduced when the first item was moved after \cs{s_@@_stop}), and
+%   leaves its argument~|#1| within \cs{exp_not:n}.  There is also a
+%   need to remove a leading comma, hence \cs{exp_not:o} and
+%   \cs{use_none:n}.
+%    \begin{macrocode}
+\cs_new:Npn \clist_reverse:n #1
+  {
+    \@@_reverse:wwNww ? #1 ,
+      \s_@@_mark \@@_reverse:wwNww ! ,
+      \s_@@_mark \@@_reverse_end:ww
+      \s_@@_stop ? \s_@@_mark
+  }
+\cs_new:Npn \@@_reverse:wwNww
+    #1 , #2 \s_@@_mark #3 #4 \s_@@_stop ? #5 \s_@@_mark
+  { #3 ? #2 \s_@@_mark #3 #4 \s_@@_stop #1 , #5 \s_@@_mark }
+\cs_new:Npn \@@_reverse_end:ww #1 ! #2 , \s_@@_mark
+  { \exp_not:o { \use_none:n #2 } }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {\clist_sort:Nn, \clist_sort:cn, \clist_gsort:Nn, \clist_gsort:cn}
+%   Implemented in \pkg{l3sort}.
+% \end{macro}
+%
+% \subsection{Comma list conditionals}
+%
+% \begin{macro}[pTF]{\clist_if_empty:N, \clist_if_empty:c}
+% \UnitTested
+%   Simple copies from the token list variable material.
+%    \begin{macrocode}
+\prg_new_eq_conditional:NNn \clist_if_empty:N \tl_if_empty:N
+  { p , T , F , TF }
+\prg_new_eq_conditional:NNn \clist_if_empty:c \tl_if_empty:c
+  { p , T , F , TF }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, pTF]{\clist_if_empty:n}
+% \begin{macro}[EXP]{\@@_if_empty_n:w}
+% \begin{macro}[EXP]{\@@_if_empty_n:wNw}
+%   As usual, we insert a token (here |?|) before grabbing
+%   any argument: this avoids losing braces. The argument
+%   of \cs{tl_if_empty:oTF} is empty if |#1| is |?| followed
+%   by blank spaces (besides, this particular variant of
+%   the emptiness test is optimized). If the item of the
+%   comma list is blank, grab the next one. As soon as one
+%   item is non-blank, exit: the second auxiliary grabs
+%   \cs{prg_return_false:} as |#2|, unless every item in
+%   the comma list was blank and the loop actually got broken
+%   by the trailing \cs{s_@@_mark} \cs{prg_return_false:} item.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \clist_if_empty:n #1 { p , T , F , TF }
+  {
+    \@@_if_empty_n:w ? #1
+    , \s_@@_mark \prg_return_false:
+    , \s_@@_mark \prg_return_true:
+    \s_@@_stop
+  }
+\cs_new:Npn \@@_if_empty_n:w #1 ,
+  {
+    \tl_if_empty:oTF { \use_none:nn #1 ? }
+      { \@@_if_empty_n:w ? }
+      { \@@_if_empty_n:wNw }
+  }
+\cs_new:Npn \@@_if_empty_n:wNw #1 \s_@@_mark #2#3 \s_@@_stop {#2}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[TF]
+%   {
+%     \clist_if_in:Nn, \clist_if_in:NV, \clist_if_in:No,
+%     \clist_if_in:cn, \clist_if_in:cV, \clist_if_in:co,
+%     \clist_if_in:nn, \clist_if_in:nV, \clist_if_in:no
+%   }
+% \begin{macro}{\@@_if_in_return:nnN}
+% \UnitTested
+%   For \enquote{safe} items, we simply surround the comma list, and the
+%   item, with commas, then use the same code as for \cs{tl_if_in:Nn}.
+%   For \enquote{unsafe} items we follow the same route as
+%   \cs{seq_if_in:Nn}, mapping through the list a comparison function.
+%   If found, return \texttt{true} and remove \cs{prg_return_false:}.
+%    \begin{macrocode}
+\prg_new_protected_conditional:Npnn \clist_if_in:Nn #1#2 { T  , F , TF }
+  {
+    \exp_args:No \@@_if_in_return:nnN #1 {#2} #1
+  }
+\prg_new_protected_conditional:Npnn \clist_if_in:nn #1#2 { T  , F , TF }
+  {
+    \clist_set:Nn \l_@@_internal_clist {#1}
+    \exp_args:No \@@_if_in_return:nnN \l_@@_internal_clist {#2}
+      \l_@@_internal_clist
+  }
+\cs_new_protected:Npn \@@_if_in_return:nnN #1#2#3
+  {
+    \@@_if_wrap:nTF {#2}
+      {
+        \cs_set:Npe \@@_tmp:w ##1
+          {
+            \exp_not:N \tl_if_eq:nnT {##1}
+            \exp_not:n
+              {
+                {#2}
+                { \clist_map_break:n { \prg_return_true: \use_none:n } }
+              }
+          }
+        \clist_map_function:NN #3 \@@_tmp:w
+        \prg_return_false:
+      }
+      {
+        \cs_set:Npn \@@_tmp:w ##1 ,#2, { }
+        \tl_if_empty:oTF
+          { \@@_tmp:w ,#1, {} {} ,#2, }
+          { \prg_return_false: } { \prg_return_true: }
+      }
+  }
+\prg_generate_conditional_variant:Nnn \clist_if_in:Nn
+  { NV , No , c , cV , co } { T , F , TF }
+\prg_generate_conditional_variant:Nnn \clist_if_in:nn
+  { nV , no } { T , F , TF }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Mapping over comma lists}
+%
+% \begin{macro}{\clist_map_function:NN, \clist_map_function:cN}
+% \UnitTested
+% \begin{macro}{\@@_map_function:Nw, \@@_map_function_end:w}
+%   If the variable is empty, the mapping is skipped (otherwise,
+%   that comma-list would be seen as consisting of one empty item).
+%   Then loop over the comma-list, grabbing eight comma-delimited items
+%   at a time. The end is marked by \cs{s_@@_stop}, which may not appear
+%   in any of the items.  Once the last group of eight items has been
+%   reached, we go through them more slowly using
+%   \cs{@@_map_function_end:w}.  The auxiliary function
+%   \cs{@@_map_function:Nw} is also used in some other clist mappings.
+%    \begin{macrocode}
+\cs_new:Npn \clist_map_function:NN #1#2
+  {
+    \clist_if_empty:NF #1
+      {
+        \exp_after:wN \@@_map_function:Nw \exp_after:wN #2 #1 ,
+          \s_@@_stop , \s_@@_stop , \s_@@_stop , \s_@@_stop ,
+          \s_@@_stop , \s_@@_stop , \s_@@_stop , \s_@@_stop ,
+        \prg_break_point:Nn \clist_map_break: { }
+      }
+  }
+\cs_new:Npn \@@_map_function:Nw #1 #2, #3, #4, #5, #6, #7, #8, #9,
+  {
+    \@@_use_none_delimit_by_s_stop:w
+      #9 \@@_map_function_end:w \s_@@_stop
+    #1 {#2} #1 {#3} #1 {#4} #1 {#5} #1 {#6} #1 {#7} #1 {#8} #1 {#9}
+    \@@_map_function:Nw #1
+  }
+\cs_new:Npn \@@_map_function_end:w \s_@@_stop #1#2
+  {
+    \@@_use_none_delimit_by_s_stop:w #2 \clist_map_break: \s_@@_stop
+    #1 {#2}
+    \@@_map_function_end:w \s_@@_stop
+  }
+\cs_generate_variant:Nn \clist_map_function:NN { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_map_function:nN, \clist_map_function:eN}
+% \UnitTested
+% \begin{macro}{\@@_map_function_n:Nn}
+% \begin{macro}{\@@_map_unbrace:wn}
+%   The \texttt{n}-type mapping function is a bit more awkward,
+%   since spaces must be trimmed from each item.
+%   Space trimming is again based on \cs{@@_trim_next:w}.
+%   The auxiliary \cs{@@_map_function_n:Nn} receives as arguments the
+%   function, and the next non-empty item (after space trimming but
+%   before brace removal).  One level of braces is removed by
+%   \cs{@@_map_unbrace:wn}.
+%    \begin{macrocode}
+\cs_new:Npn \clist_map_function:nN #1#2
+  {
+    \exp_after:wN \@@_map_function_n:Nn \exp_after:wN #2
+    \exp:w \@@_trim_next:w \prg_do_nothing: #1 ,
+      \s_@@_stop \clist_map_break: ,
+    \prg_break_point:Nn \clist_map_break: { }
+  }
+\cs_generate_variant:Nn \clist_map_function:nN { e }
+\cs_new:Npn \@@_map_function_n:Nn #1 #2
+  {
+    \@@_use_none_delimit_by_s_stop:w #2 \s_@@_stop
+    \@@_map_unbrace:wn #2 , #1
+    \exp_after:wN \@@_map_function_n:Nn \exp_after:wN #1
+    \exp:w \@@_trim_next:w \prg_do_nothing:
+  }
+\cs_new:Npn \@@_map_unbrace:wn #1, #2 { #2 {#1} }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_map_inline:Nn, \clist_map_inline:cn}
+% \UnitTested
+% \begin{macro}{\clist_map_inline:nn}
+% \UnitTested
+%   Inline mapping is done by creating a suitable function
+%   \enquote{on the fly}: this is done globally to avoid
+%   any issues with \TeX{}'s groups.  We use a different
+%   function for each level of nesting.
+%
+%   Since the mapping is non-expandable,  we can perform
+%   the space-trimming  needed by the \texttt{n} version
+%   simply  by storing the comma-list in a variable.  We
+%   don't need  a different comma-list  for each nesting
+%   level: the comma-list is expanded before the mapping
+%   starts.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_map_inline:Nn #1#2
+  {
+    \clist_if_empty:NF #1
+      {
+        \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_last_unbraced:Nco \@@_map_function:Nw
+          { @@_map_ \int_use:N \g__kernel_prg_map_int :w }
+          #1 ,
+          \s_@@_stop , \s_@@_stop , \s_@@_stop , \s_@@_stop ,
+          \s_@@_stop , \s_@@_stop , \s_@@_stop , \s_@@_stop ,
+        \prg_break_point:Nn \clist_map_break:
+          { \int_gdecr:N \g__kernel_prg_map_int }
+      }
+  }
+\cs_new_protected:Npn \clist_map_inline:nn #1
+  {
+    \clist_set:Nn \l_@@_internal_clist {#1}
+    \clist_map_inline:Nn \l_@@_internal_clist
+  }
+\cs_generate_variant:Nn \clist_map_inline:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_map_variable:NNn, \clist_map_variable:cNn}
+% \UnitTested
+% \begin{macro}{\clist_map_variable:nNn}
+% \begin{macro}{\@@_map_variable:Nnn}
+%   The |N|-type version is a straightforward application of
+%   \cs{clist_map_tokens:Nn}, calling \cs{@@_map_variable:Nnn} for each
+%   item to assign the variable and run the user's code.  The |n|-type
+%   version is \emph{not} implemented in terms of the |n|-type function
+%   \cs{clist_map_tokens:Nn}, because here we are allowed to clean up
+%   the |n|-type comma list non-expandably.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_map_variable:NNn #1#2#3
+  { \clist_map_tokens:Nn #1 { \@@_map_variable:Nnn #2 {#3} } }
+\cs_generate_variant:Nn \clist_map_variable:NNn { c }
+\cs_new_protected:Npn \@@_map_variable:Nnn #1#2#3
+  { \tl_set:Nn #1 {#3} #2 }
+\cs_new_protected:Npn \clist_map_variable:nNn #1
+  {
+    \clist_set:Nn \l_@@_internal_clist {#1}
+    \clist_map_variable:NNn \l_@@_internal_clist
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_map_tokens:Nn, \clist_map_tokens:cn}
+% \begin{macro}{\@@_map_tokens:nw, \@@_map_tokens_end:w}
+%   Essentially a copy of \cs{clist_map_function:NN} with braces added.
+%    \begin{macrocode}
+\cs_new:Npn \clist_map_tokens:Nn #1#2
+  {
+    \clist_if_empty:NF #1
+      {
+        \exp_last_unbraced:Nno \@@_map_tokens:nw {#2} #1 ,
+          \s_@@_stop , \s_@@_stop , \s_@@_stop , \s_@@_stop ,
+          \s_@@_stop , \s_@@_stop , \s_@@_stop , \s_@@_stop ,
+        \prg_break_point:Nn \clist_map_break: { }
+      }
+  }
+\cs_new:Npn \@@_map_tokens:nw #1 #2, #3, #4, #5, #6, #7, #8, #9,
+  {
+    \@@_use_none_delimit_by_s_stop:w
+      #9 \@@_map_tokens_end:w \s_@@_stop
+    \use:n {#1} {#2} \use:n {#1} {#3} \use:n {#1} {#4} \use:n {#1} {#5}
+    \use:n {#1} {#6} \use:n {#1} {#7} \use:n {#1} {#8} \use:n {#1} {#9}
+    \@@_map_tokens:nw {#1}
+  }
+\cs_new:Npn \@@_map_tokens_end:w \s_@@_stop \use:n #1#2
+  {
+    \@@_use_none_delimit_by_s_stop:w #2 \clist_map_break: \s_@@_stop
+    #1 {#2}
+    \@@_map_tokens_end:w \s_@@_stop
+  }
+\cs_generate_variant:Nn \clist_map_tokens:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_map_tokens:nn, \@@_map_tokens_n:nw}
+%   Similar to \cs{clist_map_function:nN} but with a different way of
+%   grabbing items because we cannot use \cs{exp_after:wN} to pass the
+%   \meta{code}.
+%    \begin{macrocode}
+\cs_new:Npn \clist_map_tokens:nn #1#2
+  {
+    \@@_map_tokens_n:nw {#2}
+    \prg_do_nothing: #1 , \s_@@_stop \clist_map_break: ,
+    \prg_break_point:Nn \clist_map_break: { }
+  }
+\cs_new:Npn \@@_map_tokens_n:nw #1#2 ,
+  {
+    \tl_if_empty:oF { \use_none:nn #2 ? }
+      {
+        \@@_use_none_delimit_by_s_stop:w #2 \s_@@_stop
+        \tl_trim_spaces_apply:oN {#2} \use_ii_i:nn
+        \@@_map_unbrace:wn , {#1}
+      }
+    \@@_map_tokens_n:nw {#1} \prg_do_nothing:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\clist_map_break:, \clist_map_break:n}
+%   The break statements use the general \cs{prg_map_break:Nn} mechanism.
+%    \begin{macrocode}
+\cs_new:Npn \clist_map_break:
+  { \prg_map_break:Nn \clist_map_break: { } }
+\cs_new:Npn \clist_map_break:n
+  { \prg_map_break:Nn \clist_map_break: }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\clist_count:N, \clist_count:c, \clist_count:n, \clist_count:e}
+% \begin{macro}{\@@_count:n}
+% \begin{macro}{\@@_count:w}
+%   Counting the items in a comma list is done using the same approach as for
+%   other token count functions: turn each entry into a \texttt{+1} then use
+%   integer evaluation to actually do the mathematics.
+%   In the case of an \texttt{n}-type comma-list, we could of course use
+%   \cs{clist_map_function:nN}, but that is very slow, because it carefully
+%   removes spaces. Instead, we loop manually, and skip blank items
+%   (but not |{}|, hence the extra spaces).
+%    \begin{macrocode}
+\cs_new:Npn \clist_count:N #1
+  {
+    \int_eval:n
+      {
+        0
+        \clist_map_function:NN #1 \@@_count:n
+      }
+  }
+\cs_generate_variant:Nn \clist_count:N { c }
+\cs_new:Npn \@@_count:n #1 { + 1 }
+\cs_set_protected:Npn \@@_tmp:w #1
+  {
+    \cs_new:Npn \clist_count:n ##1
+      {
+        \int_eval:n
+          {
+            0
+            \@@_count:w #1
+            ##1 , \s_@@_stop \prg_break: , \prg_break_point:
+          }
+      }
+    \cs_new:Npn \@@_count:w ##1 ,
+      {
+        \@@_use_none_delimit_by_s_stop:w ##1 \s_@@_stop
+        \tl_if_blank:nF {##1} { + 1 }
+        \@@_count:w #1
+      }
+  }
+\exp_args:No \@@_tmp:w \c_space_tl
+\cs_generate_variant:Nn \clist_count:n { e }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Using comma lists}
+%
+% \begin{macro}[EXP]{\clist_use:Nnnn, \clist_use:cnnn}
+% \begin{macro}[EXP]
+%   {\@@_use:wwn, \@@_use:nwwwwnwn, \@@_use:nwwn}
+% \begin{macro}[EXP]{\clist_use:Nn, \clist_use:cn}
+%   First check that the variable exists.  Then count the items in the
+%   comma list.  If it has none, output nothing.  If it has one item,
+%   output that item, brace stripped (note that space-trimming has
+%   already been done when the comma list was assigned).  If it has two,
+%   place the \meta{separator~between~two} in the middle.
+%
+%   Otherwise, \cs{@@_use:nwwwwnwn} takes the following arguments; 1:
+%   a \meta{separator}, 2, 3, 4: three items from the comma list (or
+%   quarks), 5: the rest of the comma list, 6: a \meta{continuation}
+%   function (\texttt{use_ii} or \texttt{use_iii} with its
+%   \meta{separator} argument), 7: junk, and 8: the temporary result,
+%   which is built in a brace group following \cs{s_@@_stop}.  The
+%   \meta{separator} and the first of the three items are placed in the
+%   result, then we use the \meta{continuation}, placing the remaining
+%   two items after it.  When we begin this loop, the three items really
+%   belong to the comma list, the first \cs{s_@@_mark} is taken as a
+%   delimiter to the \texttt{use_ii} function, and the continuation is
+%   \texttt{use_ii} itself.  When we reach the last two items of the
+%   original token list, \cs{s_@@_mark} is taken as a third item, and now
+%   the second \cs{s_@@_mark} serves as a delimiter to \texttt{use_ii},
+%   switching to the other \meta{continuation}, \texttt{use_iii}, which
+%   uses the \meta{separator between final two}.
+%    \begin{macrocode}
+\cs_new:Npn \clist_use:Nnnn #1#2#3#4
+  {
+    \clist_if_exist:NTF #1
+      {
+        \int_case:nnF { \clist_count:N #1 }
+          {
+            { 0 } { }
+            { 1 } { \exp_after:wN \@@_use:wwn #1 , , { } }
+            { 2 } { \exp_after:wN \@@_use:wwn #1 , {#2} }
+          }
+          {
+            \exp_after:wN \@@_use:nwwwwnwn
+            \exp_after:wN { \exp_after:wN } #1 ,
+            \s_@@_mark , { \@@_use:nwwwwnwn {#3} }
+            \s_@@_mark , { \@@_use:nwwn {#4} }
+            \s_@@_stop { }
+          }
+      }
+      {
+        \msg_expandable_error:nnn
+          { kernel } { bad-variable } {#1}
+      }
+  }
+\cs_generate_variant:Nn \clist_use:Nnnn { c }
+\cs_new:Npn \@@_use:wwn #1 , #2 , #3 { \exp_not:n { #1 #3 #2 } }
+\cs_new:Npn \@@_use:nwwwwnwn
+    #1#2 , #3 , #4 , #5 \s_@@_mark , #6#7 \s_@@_stop #8
+  { #6 {#3} , {#4} , #5 \s_@@_mark , {#6} #7 \s_@@_stop { #8 #1 #2 } }
+\cs_new:Npn \@@_use:nwwn #1#2 , #3 \s_@@_stop #4
+  { \exp_not:n { #4 #1 #2 } }
+\cs_new:Npn \clist_use:Nn #1#2
+  { \clist_use:Nnnn #1 {#2} {#2} {#2} }
+\cs_generate_variant:Nn \clist_use:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \clist_use:nnnn, \clist_use:nn, \@@_use:Nw,
+%     \@@_use_one:w, \@@_use_end:w, \@@_use_more:w
+%   }
+%   Items are grabbed by \cs{@@_use:Nw}, which detects blank items with
+%   a \cs{tl_if_empty:oTF} test (in which case it recurses).  Non-blank
+%   items are either the end of the list, in which case the argument
+%   |#1| of \cs{@@_use:Nw} is used to properly end the list, or are
+%   normal items, which must be trimmed and properly unbraced.  As we
+%   find successive items, the long list of \cs{@@_use:Nw} calls gets
+%   shortened and we end up calling \cs{@@_use_more:w} once we have
+%   found $3$ items.  This auxiliary leaves the first-found item and the
+%   general separator, and calls \cs{@@_use:Nw} to find more items.
+%   A subtlety is that we use \cs{@@_use_end:w} both in the case of a
+%   two-item list and for the last two items of a general list: to get
+%   the correct separator, \cs{@@_use_more:w} replaces the
+%   separator-of-two by the last-separator when called, namely as soon
+%   as we have found three items.
+%    \begin{macrocode}
+\cs_new:Npn \clist_use:nnnn #1#2#3#4
+  {
+    \@@_use:Nw \@@_use_none_delimit_by_s_stop:w
+    \@@_use:Nw \@@_use_one:w
+    \@@_use:Nw \@@_use_end:w
+    \@@_use_more:w ;
+      {#2} {#3} {#4} ;
+    \prg_do_nothing: #1 , \s_@@_mark ,
+    \s_@@_stop
+  }
+\cs_new:Npn \@@_use:Nw #1#2 ; #3 ; #4 ,
+  {
+    \tl_if_empty:oTF { \use_none:nn #4 ? }
+      { \@@_use:Nw #1#2 ; }
+      {
+        \@@_use_none_delimit_by_s_mark:w #4 #1 \s_@@_mark
+        \tl_trim_spaces_apply:oN {#4} \use_ii_i:nn
+        \@@_map_unbrace:wn , { #2 ; }
+      }
+    #3 ; \prg_do_nothing:
+  }
+\cs_new:Npn \@@_use_one:w \s_@@_mark #1 , #2#3#4 \s_@@_stop
+  { \exp_not:n {#3} }
+\cs_new:Npn \@@_use_end:w
+    \s_@@_mark #1 , #2#3#4#5#6 \s_@@_stop
+  { \exp_not:n { #4 #5 #3 } }
+\cs_new:Npn \@@_use_more:w ; #1#2#3#4#5#6 ;
+  {
+    \exp_not:n { #3 #5 }
+    \@@_use:Nw \@@_use_end:w \@@_use_more:w ;
+    {#1} {#2} {#6} {#5} {#6} ;
+  }
+\cs_new:Npn \clist_use:nn #1#2 { \clist_use:nnnn {#1} {#2} {#2} {#2} }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Using a single item}
+%
+% \begin{macro}{\clist_item:Nn, \clist_item:cn}
+% \begin{macro}{\@@_item:nnnN, \@@_item:ffoN, \@@_item:ffnN}
+% \begin{macro}{\@@_item_N_loop:nw}
+%   To avoid needing to test the end of the list at each step,
+%   we first compute the \meta{length} of the list. If the item number
+%   is~$0$, less than $-\meta{length}$, or more than $\meta{length}$,
+%   the result is empty. If it is negative, but not less than $-\meta{length}$,
+%   add $\meta{length}+1$ to the item number before performing the loop.
+%   The loop itself is very simple, return the item if the counter
+%   reached~$1$, otherwise, decrease the counter and repeat.
+%    \begin{macrocode}
+\cs_new:Npn \clist_item:Nn #1#2
+  {
+    \@@_item:ffoN
+      { \clist_count:N #1 }
+      { \int_eval:n {#2} }
+      #1
+      \@@_item_N_loop:nw
+  }
+\cs_new:Npn \@@_item:nnnN #1#2#3#4
+  {
+    \int_compare:nNnTF {#2} < 0
+      {
+        \int_compare:nNnTF {#2} < { - #1 }
+          { \@@_use_none_delimit_by_s_stop:w }
+          { \exp_args:Nf #4 { \int_eval:n { #2 + 1 + #1 } } }
+      }
+      {
+        \int_compare:nNnTF {#2} > {#1}
+          { \@@_use_none_delimit_by_s_stop:w }
+          { #4 {#2} }
+      }
+    { } , #3 , \s_@@_stop
+  }
+\cs_generate_variant:Nn \@@_item:nnnN { ffo, ff }
+\cs_new:Npn \@@_item_N_loop:nw #1 #2,
+  {
+    \int_compare:nNnTF {#1} = 0
+      { \@@_use_i_delimit_by_s_stop:nw { \exp_not:n {#2} } }
+      { \exp_args:Nf \@@_item_N_loop:nw { \int_eval:n { #1 - 1 } } }
+  }
+\cs_generate_variant:Nn \clist_item:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_item:nn, \clist_item:en}
+% \begin{macro}{
+%     \@@_item_n:nw,
+%     \@@_item_n_loop:nw,
+%     \@@_item_n_end:n,
+%     \@@_item_n_strip:n,
+%     \@@_item_n_strip:w}
+%   This starts in the same way as \cs{clist_item:Nn} by counting the items
+%   of the comma list. The final item should be space-trimmed before being
+%   brace-stripped, hence we insert a couple of odd-looking
+%   \cs{prg_do_nothing:} to avoid losing braces. Blank items are ignored.
+%    \begin{macrocode}
+\cs_new:Npn \clist_item:nn #1#2
+  {
+    \@@_item:ffnN
+      { \clist_count:n {#1} }
+      { \int_eval:n {#2} }
+      {#1}
+      \@@_item_n:nw
+  }
+\cs_generate_variant:Nn \clist_item:nn { e }
+\cs_new:Npn \@@_item_n:nw #1
+  { \@@_item_n_loop:nw {#1} \prg_do_nothing: }
+\cs_new:Npn \@@_item_n_loop:nw #1 #2,
+  {
+    \exp_args:No \tl_if_blank:nTF {#2}
+      { \@@_item_n_loop:nw {#1} \prg_do_nothing: }
+      {
+        \int_compare:nNnTF {#1} = 0
+          { \exp_args:No \@@_item_n_end:n {#2} }
+          {
+            \exp_args:Nf \@@_item_n_loop:nw
+              { \int_eval:n { #1 - 1 } }
+              \prg_do_nothing:
+          }
+      }
+  }
+\cs_new:Npn \@@_item_n_end:n #1 #2 \s_@@_stop
+  { \tl_trim_spaces_apply:nN {#1} \@@_item_n_strip:n }
+\cs_new:Npn \@@_item_n_strip:n #1 { \@@_item_n_strip:w #1 , }
+\cs_new:Npn \@@_item_n_strip:w #1 , { \exp_not:n {#1} }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_rand_item:n, \clist_rand_item:N, \clist_rand_item:c}
+% \begin{macro}{\@@_rand_item:nn}
+%   The |N|-type function is not implemented through the |n|-type
+%   function for efficiency: for instance comma-list variables do not
+%   require space-trimming of their items.  Even testing for emptyness
+%   of an |n|-type comma-list is slow, so we count items first and use
+%   that both for the emptyness test and the pseudo-random integer.
+%   Importantly, \cs{clist_item:Nn} and \cs{clist_item:nn} only evaluate
+%   their argument once.
+%    \begin{macrocode}
+\cs_new:Npn \clist_rand_item:n #1
+  { \exp_args:Nf \@@_rand_item:nn { \clist_count:n {#1} } {#1} }
+\cs_new:Npn \@@_rand_item:nn #1#2
+  {
+    \int_compare:nNnF {#1} = 0
+      { \clist_item:nn {#2} { \int_rand:nn { 1 } {#1} } }
+  }
+\cs_new:Npn \clist_rand_item:N #1
+  {
+    \clist_if_empty:NF #1
+      { \clist_item:Nn #1 { \int_rand:nn { 1 } { \clist_count:N #1 } } }
+  }
+\cs_generate_variant:Nn \clist_rand_item:N { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Viewing comma lists}
+%
+% \begin{macro}{\clist_show:N, \clist_show:c, \clist_log:N, \clist_log:c, \@@_show:NN}
+%   Apply the general \cs{__kernel_chk_tl_type:NnnT} with \cs{exp_not:o}
+%   |#2| serving as a dummy code to prevent a check performed by this
+%   auxiliary.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_show:N { \@@_show:NN \msg_show:nneeee }
+\cs_generate_variant:Nn \clist_show:N { c }
+\cs_new_protected:Npn \clist_log:N { \@@_show:NN \msg_log:nneeee }
+\cs_generate_variant:Nn \clist_log:N { c }
+\cs_new_protected:Npn \@@_show:NN #1#2
+  {
+    \__kernel_chk_tl_type:NnnT #2 { clist } { \exp_not:o #2 }
+      {
+        \int_compare:nNnTF { \clist_count:N #2 }
+          = { \exp_args:No \clist_count:n #2 }
+          {
+            #1 { clist } { show }
+              { \token_to_str:N #2 }
+              { \clist_map_function:NN #2 \msg_show_item:n }
+              { } { }
+          }
+          {
+            \msg_error:nnee { clist } { non-clist }
+              { \token_to_str:N #2 } { \tl_to_str:N #2 }
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\clist_show:n, \clist_log:n, \@@_show:Nn}
+%   A variant of the above: no existence check, empty first argument for
+%   the message.
+%    \begin{macrocode}
+\cs_new_protected:Npn \clist_show:n { \@@_show:Nn \msg_show:nneeee }
+\cs_new_protected:Npn \clist_log:n { \@@_show:Nn \msg_log:nneeee }
+\cs_new_protected:Npn \@@_show:Nn #1#2
+  {
+    #1 { clist } { show }
+      { } { \clist_map_function:nN {#2} \msg_show_item:n } { } { }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Scratch comma lists}
+%
+% \begin{variable}{\l_tmpa_clist, \l_tmpb_clist}
+% \begin{variable}{\g_tmpa_clist, \g_tmpb_clist}
+%   Temporary comma list variables.
+%    \begin{macrocode}
+\clist_new:N \l_tmpa_clist
+\clist_new:N \l_tmpb_clist
+\clist_new:N \g_tmpa_clist
+\clist_new:N \g_tmpb_clist
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3clist.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3coffins.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3coffins.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3coffins.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,2590 @@
+% \iffalse meta-comment
+%
+%% File: l3coffins.dtx
+%
+% Copyright (C) 2010-2024 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 \pkg{l3coffins} module\\ Coffin code layer^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% The material in this module provides the low-level support system
+% for coffins. For details about the design concept of a coffin, see
+% the \pkg{xcoffins} module (in the \pkg{l3experimental} bundle).
+%
+% \section{Creating and initialising coffins}
+%
+% \begin{function}[added = 2011-08-17]{\coffin_new:N, \coffin_new:c}
+%   \begin{syntax}
+%     \cs{coffin_new:N} \meta{coffin}
+%   \end{syntax}
+%   Creates a new \meta{coffin} or raises an error if the name is
+%   already taken. The declaration is global. The \meta{coffin} is
+%   initially empty.
+% \end{function}
+%
+% \begin{function}[added = 2011-08-17, updated = 2019-01-21]
+%   {
+%     \coffin_clear:N, \coffin_clear:c,
+%     \coffin_gclear:N, \coffin_gclear:c
+%   }
+%   \begin{syntax}
+%     \cs{coffin_clear:N} \meta{coffin}
+%   \end{syntax}
+%   Clears the content of the \meta{coffin}.
+% \end{function}
+%
+% \begin{function}[added = 2011-08-17, updated = 2019-01-21]
+%  {
+%    \coffin_set_eq:NN, \coffin_set_eq:Nc,
+%    \coffin_set_eq:cN, \coffin_set_eq:cc,
+%    \coffin_gset_eq:NN, \coffin_gset_eq:Nc,
+%    \coffin_gset_eq:cN, \coffin_gset_eq:cc
+%  }
+%   \begin{syntax}
+%    \cs{coffin_set_eq:NN} \meta{coffin_1} \meta{coffin_2}
+%   \end{syntax}
+%   Sets both the content and poles of \meta{coffin_1} equal to those
+%   of \meta{coffin_2}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2012-06-20]
+%   {\coffin_if_exist:N, \coffin_if_exist:c}
+%   \begin{syntax}
+%     \cs{coffin_if_exist_p:N} \meta{coffin}
+%     \cs{coffin_if_exist:NTF} \meta{coffin} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{coffin} is currently defined.
+% \end{function}
+%
+% \section{Setting coffin content and poles}
+%
+% \begin{function}[added = 2011-08-17, updated = 2019-01-21]
+%   {
+%     \hcoffin_set:Nn, \hcoffin_set:cn,
+%     \hcoffin_gset:Nn, \hcoffin_gset:cn
+%   }
+%   \begin{syntax}
+%     \cs{hcoffin_set:Nn} \meta{coffin} \Arg{material}
+%   \end{syntax}
+%   Typesets the \meta{material} in horizontal mode, storing the result
+%   in the \meta{coffin}. The standard poles for the \meta{coffin} are
+%   then set up based on the size of the typeset material.
+% \end{function}
+%
+% \begin{function}[added = 2011-09-10, updated = 2019-01-21]
+%   {
+%     \hcoffin_set:Nw, \hcoffin_set:cw, \hcoffin_set_end:,
+%     \hcoffin_gset:Nw, \hcoffin_gset:cw, \hcoffin_gset_end:
+%   }
+%   \begin{syntax}
+%     \cs{hcoffin_set:Nw} \meta{coffin} \meta{material} \cs{hcoffin_set_end:}
+%   \end{syntax}
+%   Typesets the \meta{material} in horizontal mode, storing the result
+%   in the \meta{coffin}. The standard poles for the \meta{coffin} are
+%   then set up based on the size of the typeset material.
+%   These functions are useful for setting the entire contents of an
+%   environment in a coffin.
+% \end{function}
+%
+% \begin{function}[added = 2011-08-17, updated = 2023-02-03]
+%   {
+%     \vcoffin_set:Nnn, \vcoffin_set:cnn,
+%     \vcoffin_gset:Nnn, \vcoffin_gset:cnn
+%   }
+%   \begin{syntax}
+%     \cs{vcoffin_set:Nnn} \meta{coffin} \Arg{width} \Arg{material}
+%   \end{syntax}
+%   Typesets the \meta{material} in vertical mode constrained to the
+%   given \meta{width} and stores the result in the \meta{coffin}. The
+%   standard poles for the \meta{coffin} are then set up based on the
+%   size of the typeset material.
+% \end{function}
+%
+% \begin{function}[added = 2011-09-10, updated = 2023-02-03]
+%   {
+%     \vcoffin_set:Nnw, \vcoffin_set:cnw, \vcoffin_set_end:,
+%     \vcoffin_gset:Nnw, \vcoffin_gset:cnw, \vcoffin_gset_end:
+%   }
+%   \begin{syntax}
+%     \cs{vcoffin_set:Nnw} \meta{coffin} \Arg{width} \meta{material} \cs{vcoffin_set_end:}
+%   \end{syntax}
+%   Typesets the \meta{material} in vertical mode constrained to the
+%   given \meta{width} and stores the result in the \meta{coffin}. The
+%   standard poles for the \meta{coffin} are then set up based on the
+%   size of the typeset material.
+%   These functions are useful for setting the entire contents of an
+%   environment in a coffin.
+% \end{function}
+%
+% \begin{function}[added = 2012-07-20, updated = 2019-01-21]
+%   {
+%     \coffin_set_horizontal_pole:Nnn, \coffin_set_horizontal_pole:cnn,
+%     \coffin_gset_horizontal_pole:Nnn, \coffin_gset_horizontal_pole:cnn
+%   }
+%   \begin{syntax}
+%     \cs{coffin_set_horizontal_pole:Nnn} \meta{coffin}
+%     ~~\Arg{pole} \Arg{offset}
+%   \end{syntax}
+%   Sets the \meta{pole} to run horizontally through the \meta{coffin}.
+%   The \meta{pole} is placed at the \meta{offset} from the
+%   baseline of the \meta{coffin}. The
+%   \meta{offset} should be given as a dimension expression.
+% \end{function}
+%
+% \begin{function}[added = 2012-07-20, updated = 2019-01-21]
+%   {
+%     \coffin_set_vertical_pole:Nnn, \coffin_set_vertical_pole:cnn,
+%     \coffin_gset_vertical_pole:Nnn, \coffin_gset_vertical_pole:cnn
+%   }
+%   \begin{syntax}
+%     \cs{coffin_set_vertical_pole:Nnn} \meta{coffin} \Arg{pole} \Arg{offset}
+%   \end{syntax}
+%   Sets the \meta{pole} to run vertically through the \meta{coffin}.
+%   The \meta{pole} is placed at the \meta{offset} from the
+%   left-hand edge of the bounding box of the \meta{coffin}. The
+%   \meta{offset} should be given as a dimension expression.
+% \end{function}
+%
+% \begin{function}[added = 2023-05-17]{\coffin_reset_poles:N, \coffin_greset_poles:N}
+%   \begin{syntax}
+%     \cs{coffin_reset_poles:N} \meta{coffin}
+%   \end{syntax}
+%   Resets the poles of the \meta{coffin} to the standard set, removing any
+%   custom or inherited poles. The poles will therefore be equal to those that
+%   would be obtained from \cs{hcoffin_set:Nn} or similar; the bounding box
+%   of the coffin is not reset, so any material outside of the formal bounding box
+%   will not influence the poles.
+% \end{function}
+%
+% \section{Coffin affine transformations}
+%
+% \begin{function}[updated = 2019-01-23]
+%   {
+%     \coffin_resize:Nnn, \coffin_resize:cnn,
+%     \coffin_gresize:Nnn, \coffin_gresize:cnn
+%   }
+%   \begin{syntax}
+%     \cs{coffin_resize:Nnn} \meta{coffin} \Arg{width} \Arg{total-height}
+%   \end{syntax}
+%   Resized the \meta{coffin} to \meta{width} and \meta{total-height},
+%   both of which should be given as dimension expressions.
+% \end{function}
+%
+% \begin{function}
+%   {
+%     \coffin_rotate:Nn, \coffin_rotate:cn,
+%     \coffin_grotate:Nn, \coffin_grotate:cn
+%   }
+%   \begin{syntax}
+%     \cs{coffin_rotate:Nn} \meta{coffin} \Arg{angle}
+%   \end{syntax}
+%   Rotates the \meta{coffin} by the given \meta{angle} (given in
+%   degrees counter-clockwise). This process rotates both the
+%   coffin content and poles. Multiple rotations do not result in
+%   the bounding box of the coffin growing unnecessarily.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-23]
+%   {
+%     \coffin_scale:Nnn, \coffin_scale:cnn,
+%     \coffin_gscale:Nnn, \coffin_gscale:cnn
+%   }
+%   \begin{syntax}
+%     \cs{coffin_scale:Nnn} \meta{coffin} \Arg{x-scale} \Arg{y-scale}
+%   \end{syntax}
+%   Scales the \meta{coffin} by a factors \meta{x-scale} and
+%   \meta{y-scale} in the horizontal and vertical directions,
+%   respectively. The two scale factors should be given as real numbers.
+% \end{function}
+%
+% \section{Joining and using coffins}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \coffin_attach:NnnNnnnn, \coffin_attach:cnnNnnnn,
+%     \coffin_attach:Nnncnnnn, \coffin_attach:cnncnnnn,
+%     \coffin_gattach:NnnNnnnn, \coffin_gattach:cnnNnnnn,
+%     \coffin_gattach:Nnncnnnn, \coffin_gattach:cnncnnnn
+%   }
+%   \begin{syntax}
+%     \cs{coffin_attach:NnnNnnnn}
+%     ~~\meta{coffin_1} \Arg{coffin_1-pole_1} \Arg{coffin_1-pole_2}
+%     ~~\meta{coffin_2} \Arg{coffin_2-pole_1} \Arg{coffin_2-pole_2}
+%     ~~\Arg{x-offset} \Arg{y-offset}
+%   \end{syntax}
+%   This function attaches \meta{coffin_2} to \meta{coffin_1} such that the bounding box
+%   of \meta{coffin_1} is not altered, \emph{i.e.}~\meta{coffin_2} can
+%   protrude outside of the bounding box of the coffin. The alignment
+%   is carried out by first calculating \meta{handle_1}, the
+%   point of intersection of \meta{coffin_1-pole_1} and
+%   \meta{coffin_1-pole_2}, and \meta{handle_2}, the point of intersection
+%   of \meta{coffin_2-pole_1} and \meta{coffin_2-pole_2}. \meta{coffin_2} is
+%   then attached to \meta{coffin_1} such that the relationship between
+%   \meta{handle_1} and \meta{handle_2} is described by the \meta{x-offset}
+%   and \meta{y-offset}. The two offsets should be given as dimension
+%   expressions.
+% \end{function}
+%
+% \begin{function}[updated = 2019-01-22]
+%   {
+%     \coffin_join:NnnNnnnn, \coffin_join:cnnNnnnn,
+%     \coffin_join:Nnncnnnn, \coffin_join:cnncnnnn,
+%     \coffin_gjoin:NnnNnnnn, \coffin_gjoin:cnnNnnnn,
+%     \coffin_gjoin:Nnncnnnn, \coffin_gjoin:cnncnnnn
+%   }
+%   \begin{syntax}
+%     \cs{coffin_join:NnnNnnnn}
+%     ~~\meta{coffin_1} \Arg{coffin_1-pole_1} \Arg{coffin_1-pole_2}
+%     ~~\meta{coffin_2} \Arg{coffin_2-pole_1} \Arg{coffin_2-pole_2}
+%     ~~\Arg{x-offset} \Arg{y-offset}
+%   \end{syntax}
+%   This function joins \meta{coffin_2} to \meta{coffin_1} such that the bounding box
+%   of \meta{coffin_1} may expand. The new bounding
+%   box covers the area containing the bounding boxes of the two
+%   original coffins. The alignment is carried out by first calculating
+%   \meta{handle_1}, the point of intersection of \meta{coffin_1-pole_1} and
+%   \meta{coffin_1-pole_2}, and \meta{handle_2}, the point of intersection
+%   of \meta{coffin_2-pole_1} and \meta{coffin_2-pole_2}. \meta{coffin_2} is
+%   then attached to \meta{coffin_1} such that the relationship between
+%   \meta{handle_1} and \meta{handle_2} is described by the \meta{x-offset}
+%   and \meta{y-offset}. The two offsets should be given as dimension
+%   expressions.
+% \end{function}
+%
+% \begin{function}[updated = 2012-07-20]
+%   {\coffin_typeset:Nnnnn, \coffin_typeset:cnnnn}
+%   \begin{syntax}
+%     \cs{coffin_typeset:Nnnnn} \meta{coffin} \Arg{pole_1} \Arg{pole_2}
+%     ~~\Arg{x-offset} \Arg{y-offset}
+%   \end{syntax}
+%   Typesetting is carried out by first calculating \meta{handle}, the
+%   point of intersection of \meta{pole_1} and \meta{pole_2}. The coffin
+%   is then typeset in horizontal mode such that the relationship between the
+%   current reference point in the document and the \meta{handle} is described
+%   by the \meta{x-offset} and \meta{y-offset}. The two offsets should
+%   be given as dimension expressions. Typesetting a coffin is
+%   therefore analogous to carrying out an alignment where the
+%   \enquote{parent} coffin is the current insertion point.
+% \end{function}
+%
+% \section{Measuring coffins}
+%
+% \begin{function}{\coffin_dp:N, \coffin_dp:c}
+%   \begin{syntax}
+%     \cs{coffin_dp:N} \meta{coffin}
+%   \end{syntax}
+%   Calculates the depth (below the baseline) of the \meta{coffin}
+%   in a form suitable for use in a \meta{dim expr}.
+% \end{function}
+%
+% \begin{function}{\coffin_ht:N, \coffin_ht:c}
+%   \begin{syntax}
+%     \cs{coffin_ht:N} \meta{coffin}
+%   \end{syntax}
+%   Calculates the height (above the baseline) of the \meta{coffin}
+%   in a form suitable for use in a \meta{dim expr}.
+% \end{function}
+%
+% \begin{function}{\coffin_wd:N, \coffin_wd:c}
+%   \begin{syntax}
+%     \cs{coffin_wd:N} \meta{coffin}
+%   \end{syntax}
+%   Calculates the width of the \meta{coffin} in a form
+%   suitable for use in a \meta{dim expr}.
+% \end{function}
+%
+% \section{Coffin diagnostics}
+%
+% \begin{function}[updated = 2011-09-02]
+%   {\coffin_display_handles:Nn, \coffin_display_handles:cn}
+%   \begin{syntax}
+%     \cs{coffin_display_handles:Nn} \meta{coffin} \Arg{color}
+%   \end{syntax}
+%   This function first calculates the intersections between all of
+%   the \meta{poles} of the \meta{coffin} to give a set of
+%   \meta{handles}. It then prints the  \meta{coffin} at the current
+%   location in the source, with the  position of the \meta{handles}
+%   marked on the coffin. The \meta{handles} are labelled as part
+%   of this process: the locations of the \meta{handles} and the labels
+%   are both printed in the \meta{color} specified.
+% \end{function}
+%
+% \begin{function}[updated = 2011-09-02]
+%   {\coffin_mark_handle:Nnnn, \coffin_mark_handle:cnnn}
+%   \begin{syntax}
+%     \cs{coffin_mark_handle:Nnnn} \meta{coffin} \Arg{pole_1} \Arg{pole_2} \Arg{color}
+%   \end{syntax}
+%   This function first calculates the \meta{handle} for the
+%   \meta{coffin} as defined by the intersection of \meta{pole_1} and
+%   \meta{pole_2}. It then marks the position of the \meta{handle}
+%   on the \meta{coffin}. The \meta{handle} are labelled as part of
+%   this process: the location of the \meta{handle} and the label are
+%   both printed in the \meta{color} specified.
+% \end{function}
+%
+% \begin{function}[updated = 2015-08-01]
+%   {\coffin_show_structure:N, \coffin_show_structure:c}
+%   \begin{syntax}
+%     \cs{coffin_show_structure:N} \meta{coffin}
+%   \end{syntax}
+%   This function shows the structural information about the
+%   \meta{coffin} in the terminal. The width, height and depth of the
+%   typeset material are given, along with the location of all of the
+%   poles of the coffin.
+%
+%   Notice that the poles of a coffin are defined by four values:
+%   the $x$ and $y$ co-ordinates of a point that the pole
+%   passes through and the $x$- and $y$-components of a
+%   vector denoting the direction of the pole. It is the ratio between
+%   the later, rather than the absolute values, which determines the
+%   direction of the pole.
+% \end{function}
+%
+% \begin{function}[added = 2014-08-22, updated = 2015-08-01]
+%   {\coffin_log_structure:N, \coffin_log_structure:c}
+%   \begin{syntax}
+%     \cs{coffin_log_structure:N} \meta{coffin}
+%   \end{syntax}
+%   This function writes the structural information about the
+%   \meta{coffin} in the log file. See also \cs{coffin_show_structure:N}
+%   which displays the result in the terminal.
+% \end{function}
+%
+% \begin{function}[added = 2021-05-11]
+%   {\coffin_show:N, \coffin_show:c, \coffin_log:N, \coffin_log:c}
+%   \begin{syntax}
+%     \cs{coffin_show:N} \meta{coffin}
+%     \cs{coffin_log:N} \meta{coffin}
+%   \end{syntax}
+%   Shows full details of poles and contents of the \meta{coffin} in the
+%   terminal or log file.  See \cs{coffin_show_structure:N} and
+%   \cs{box_show:N} to show separately the pole structure and the
+%   contents.
+% \end{function}
+%
+% \begin{function}[added = 2021-05-11]
+%   {\coffin_show:Nnn, \coffin_show:cnn, \coffin_log:Nnn, \coffin_log:cnn}
+%   \begin{syntax}
+%     \cs{coffin_show:Nnn} \meta{coffin} \Arg{int expr_1} \Arg{int expr_2}
+%     \cs{coffin_log:Nnn} \meta{coffin} \Arg{int expr_1} \Arg{int expr_2}
+%   \end{syntax}
+%   Shows poles and contents of the \meta{coffin} in the terminal or log
+%   file, showing the first \meta{int expr_1} items in the coffin, and
+%   descending into \meta{int expr_2} group levels.  See
+%   \cs{coffin_show_structure:N} and \cs{box_show:Nnn} to show
+%   separately the pole structure and the contents.
+% \end{function}
+%
+% \section{Constants and variables}
+%
+% \begin{variable}{\c_empty_coffin}
+%   A permanently empty coffin.
+% \end{variable}
+%
+% \begin{variable}[added = 2012-06-19]{\l_tmpa_coffin, \l_tmpb_coffin}
+%   Scratch coffins for local assignment. These are never used by
+%   the kernel code, and so are safe for use with any \LaTeX3-defined
+%   function. However, they may be overwritten by other non-kernel
+%   code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}[added = 2019-01-24]{\g_tmpa_coffin, \g_tmpb_coffin}
+%   Scratch coffins for global assignment. These are never used by
+%   the kernel code, and so are safe for use with any \LaTeX3-defined
+%   function. However, they may be overwritten by other non-kernel
+%   code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3coffins} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=coffin>
+%    \end{macrocode}
+%
+% \subsection{Coffins: data structures and general variables}
+%
+% \begin{variable}{\l_@@_internal_box}
+% \begin{variable}{\l_@@_internal_dim}
+% \begin{variable}{\l_@@_internal_tl}
+%   Scratch variables.
+%    \begin{macrocode}
+\box_new:N \l_@@_internal_box
+\dim_new:N \l_@@_internal_dim
+\tl_new:N  \l_@@_internal_tl
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\c_@@_corners_prop}
+%   The \enquote{corners}; of a coffin define the real content, as
+%   opposed to the \TeX{} bounding box. They all start off in the same
+%   place, of course.
+%    \begin{macrocode}
+\prop_const_from_keyval:Nn \c_@@_corners_prop
+  {
+    tl = { 0pt } { 0pt } ,
+    tr = { 0pt } { 0pt } ,
+    bl = { 0pt } { 0pt } ,
+    br = { 0pt } { 0pt } ,
+  }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_@@_poles_prop}
+%   Pole positions are given for horizontal, vertical and reference-point
+%   based values.
+%    \begin{macrocode}
+\prop_const_from_keyval:Nn \c_@@_poles_prop
+  {
+    l  = { 0pt } { 0pt } { 0pt } { 1000pt } ,
+    hc = { 0pt } { 0pt } { 0pt } { 1000pt } ,
+    r  = { 0pt } { 0pt } { 0pt } { 1000pt } ,
+    b  = { 0pt } { 0pt } { 1000pt } { 0pt } ,
+    vc = { 0pt } { 0pt } { 1000pt } { 0pt } ,
+    t  = { 0pt } { 0pt } { 1000pt } { 0pt } ,
+    B  = { 0pt } { 0pt } { 1000pt } { 0pt } ,
+    H  = { 0pt } { 0pt } { 1000pt } { 0pt } ,
+    T  = { 0pt } { 0pt } { 1000pt } { 0pt } ,
+  }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_slope_A_fp}
+% \begin{variable}{\l_@@_slope_B_fp}
+%   Used for calculations of intersections.
+%    \begin{macrocode}
+\fp_new:N \l_@@_slope_A_fp
+\fp_new:N \l_@@_slope_B_fp
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_error_bool}
+%   For propagating errors so that parts of the code can work around them.
+%    \begin{macrocode}
+\bool_new:N \l_@@_error_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_offset_x_dim}
+% \begin{variable}{\l_@@_offset_y_dim}
+%   The offset between two sets of coffin handles when typesetting. These
+%   values are corrected from those requested in an alignment for the
+%   positions of the handles.
+%    \begin{macrocode}
+\dim_new:N \l_@@_offset_x_dim
+\dim_new:N \l_@@_offset_y_dim
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_pole_a_tl}
+% \begin{variable}{\l_@@_pole_b_tl}
+%   Needed for finding the intersection of two poles.
+%    \begin{macrocode}
+\tl_new:N \l_@@_pole_a_tl
+\tl_new:N \l_@@_pole_b_tl
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_x_dim}
+% \begin{variable}{\l_@@_y_dim}
+% \begin{variable}{\l_@@_x_prime_dim}
+% \begin{variable}{\l_@@_y_prime_dim}
+%   For calculating intersections and so forth.
+%    \begin{macrocode}
+\dim_new:N \l_@@_x_dim
+\dim_new:N \l_@@_y_dim
+\dim_new:N \l_@@_x_prime_dim
+\dim_new:N \l_@@_y_prime_dim
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+%
+% \subsection{Basic coffin functions}
+%
+% There are a number of basic functions needed for creating coffins and
+% placing material in them. This all relies on the following data
+% structures.
+%
+% \begin{macro}[EXP]{\@@_to_value:N}
+%   Coffins are a two-part structure and we rely on the internal nature of
+%   box allocation to make everything work. As such, we need an interface
+%   to turn coffin identifiers into numbers. For the purposes here, the
+%   signature allowed is |N| despite the nature of the underlying primitive.
+%    \begin{macrocode}
+\cs_new_eq:NN \@@_to_value:N \tex_number:D
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, pTF]{\coffin_if_exist:N, \coffin_if_exist:c}
+%   Several of the higher-level coffin functions would give multiple
+%   errors if the coffin does not exist. A cleaner way to handle this
+%   is provided here: both the box and the coffin structure are
+%   checked.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \coffin_if_exist:N #1 { p , T , F , TF }
+  {
+    \cs_if_exist:NTF #1
+      {
+        \cs_if_exist:cTF { coffin ~ \@@_to_value:N #1 ~ poles }
+          { \prg_return_true: }
+          { \prg_return_false: }
+      }
+      { \prg_return_false: }
+  }
+\prg_generate_conditional_variant:Nnn \coffin_if_exist:N
+  { c } { p , T , F , TF }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_if_exist:NT}
+%   Several of the higher-level coffin functions would give multiple
+%   errors if the coffin does not exist. So a wrapper is provided to deal
+%   with this correctly, issuing an error on erroneous use.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_if_exist:NT #1#2
+  {
+    \coffin_if_exist:NTF #1
+      { #2 }
+      {
+        \msg_error:nne { coffin } { unknown }
+          { \token_to_str:N #1 }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \coffin_clear:N, \coffin_clear:c,
+%     \coffin_gclear:N, \coffin_gclear:c
+%   }
+%   Clearing coffins means emptying the box and resetting all of the
+%   structures.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_clear:N #1
+  {
+    \@@_if_exist:NT #1
+      {
+        \box_clear:N #1
+        \@@_reset_structure:N #1
+      }
+  }
+\cs_generate_variant:Nn \coffin_clear:N { c }
+\cs_new_protected:Npn \coffin_gclear:N #1
+  {
+    \@@_if_exist:NT #1
+      {
+        \box_gclear:N #1
+        \@@_greset_structure:N #1
+      }
+  }
+\cs_generate_variant:Nn \coffin_gclear:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\coffin_new:N, \coffin_new:c}
+%   Creating a new coffin means making the underlying box and adding the
+%   data structures.  The \cs{debug_suspend:} and \cs{debug_resume:} functions
+%   prevent \cs{prop_gclear_new:c} from writing useless information to
+%   the log file.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_new:N #1
+  {
+    \box_new:N #1
+    \debug_suspend:
+    \prop_gclear_new:c { coffin ~ \@@_to_value:N #1 ~ corners }
+    \prop_gclear_new:c { coffin ~ \@@_to_value:N #1 ~ poles }
+    \prop_gset_eq:cN { coffin ~ \@@_to_value:N #1 ~ corners }
+      \c_@@_corners_prop
+    \prop_gset_eq:cN { coffin ~ \@@_to_value:N #1 ~ poles }
+      \c_@@_poles_prop
+    \debug_resume:
+  }
+\cs_generate_variant:Nn \coffin_new:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \hcoffin_set:Nn, \hcoffin_set:cn,
+%     \hcoffin_gset:Nn, \hcoffin_gset:cn
+%   }
+%   Horizontal coffins are relatively easy: set the appropriate box,
+%   reset the structures then update the handle positions.
+%    \begin{macrocode}
+\cs_new_protected:Npn \hcoffin_set:Nn #1#2
+  {
+    \@@_if_exist:NT #1
+      {
+        \hbox_set:Nn #1
+          {
+            \color_ensure_current:
+            #2
+          }
+        \coffin_reset_poles:N #1
+      }
+  }
+\cs_generate_variant:Nn \hcoffin_set:Nn { c }
+\cs_new_protected:Npn \hcoffin_gset:Nn #1#2
+  {
+    \@@_if_exist:NT #1
+      {
+        \hbox_gset:Nn #1
+          {
+            \color_ensure_current:
+            #2
+          }
+        \coffin_greset_poles:N #1
+      }
+  }
+\cs_generate_variant:Nn \hcoffin_gset:Nn { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \vcoffin_set:Nnn, \vcoffin_set:cnn,
+%     \vcoffin_gset:Nnn, \vcoffin_gset:cnn
+%   }
+%  \begin{macro}{\@@_set_vertical:NnnNNN}
+%  \begin{macro}{\@@_set_vertical_aux:}
+%   Setting vertical coffins is more complex. First, the material is
+%   typeset with a given width. The default handles and poles are set as
+%   for a horizontal coffin, before finding the top baseline using a
+%   temporary box. No \cs{color_ensure_current:} here as that would add a
+%   whatsit to the start of the vertical box and mess up the location of the
+%   \texttt{T}~pole (see \emph{\TeX{} by Topic} for discussion of the
+%   \tn{vtop} primitive, used to do the measuring).
+%    \begin{macrocode}
+\cs_new_protected:Npn \vcoffin_set:Nnn #1#2#3
+  {
+    \@@_set_vertical:NnnNNN #1 {#2} {#3}
+      \vbox_set:Nn \coffin_reset_poles:N \@@_set_pole:Nnn
+  }
+\cs_generate_variant:Nn \vcoffin_set:Nnn { c }
+\cs_new_protected:Npn \vcoffin_gset:Nnn #1#2#3
+  {
+    \@@_set_vertical:NnnNNN #1 {#2} {#3}
+      \vbox_gset:Nn \coffin_greset_poles:N \@@_gset_pole:Nnn
+  }
+\cs_generate_variant:Nn \vcoffin_gset:Nnn { c }
+\cs_new_protected:Npn \@@_set_vertical:NnnNNN #1#2#3#4#5#6
+  {
+    \@@_if_exist:NT #1
+      {
+        #4 #1
+          {
+            \dim_set:Nn \tex_hsize:D {#2}
+            \@@_set_vertical_aux:
+            #3
+          }
+        #5 #1
+        \vbox_set_top:Nn \l_@@_internal_box { \vbox_unpack:N #1 }
+        #6 #1 { T }
+          {
+            { 0pt }
+            {
+              \dim_eval:n
+                { \box_ht:N #1 - \box_ht:N \l_@@_internal_box }
+            }
+            { 1000pt }
+            { 0pt }
+          }
+        \box_clear:N \l_@@_internal_box
+      }
+  }
+\cs_new_protected:Npe \@@_set_vertical_aux:
+  {
+    \bool_lazy_and:nnT
+      { \cs_if_exist_p:N \fmtname }
+      { \str_if_eq_p:Vn \fmtname { LaTeX2e } }
+      {
+        \dim_set_eq:NN \exp_not:N \linewidth \tex_hsize:D
+        \dim_set_eq:NN \exp_not:N \columnwidth \tex_hsize:D
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {\hcoffin_set:Nw, \hcoffin_set:cw, \hcoffin_gset:Nw, \hcoffin_gset:cw}
+% \begin{macro}{\hcoffin_set_end:, \hcoffin_gset_end:}
+% These are the \enquote{begin}/\enquote{end} versions of the above:
+% watch the grouping!
+%    \begin{macrocode}
+\cs_new_protected:Npn \hcoffin_set:Nw #1
+  {
+    \@@_if_exist:NT #1
+      {
+        \hbox_set:Nw #1 \color_ensure_current:
+          \cs_set_protected:Npn \hcoffin_set_end:
+            {
+              \hbox_set_end:
+              \coffin_reset_poles:N #1
+            }
+      }
+  }
+\cs_generate_variant:Nn \hcoffin_set:Nw { c }
+\cs_new_protected:Npn \hcoffin_gset:Nw #1
+  {
+    \@@_if_exist:NT #1
+      {
+        \hbox_gset:Nw #1 \color_ensure_current:
+          \cs_set_protected:Npn \hcoffin_gset_end:
+            {
+              \hbox_gset_end:
+              \coffin_greset_poles:N #1
+            }
+      }
+  }
+\cs_generate_variant:Nn \hcoffin_gset:Nw { c }
+\cs_new_protected:Npn \hcoffin_set_end: { }
+\cs_new_protected:Npn \hcoffin_gset_end: { }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {\vcoffin_set:Nnw, \vcoffin_set:cnw, \vcoffin_gset:Nnw, \vcoffin_gset:cnw}
+% \begin{macro}{\@@_set_vertical:NnNNNNNw}
+% \begin{macro}{\vcoffin_set_end:, \vcoffin_gset_end:}
+%   The same for vertical coffins.
+%    \begin{macrocode}
+\cs_new_protected:Npn \vcoffin_set:Nnw #1#2
+  {
+    \@@_set_vertical:NnNNNNNw #1 {#2} \vbox_set:Nw
+      \vcoffin_set_end:
+      \vbox_set_end: \coffin_reset_poles:N \@@_set_pole:Nnn
+  }
+\cs_generate_variant:Nn \vcoffin_set:Nnw { c }
+\cs_new_protected:Npn \vcoffin_gset:Nnw #1#2
+  {
+    \@@_set_vertical:NnNNNNNw #1 {#2} \vbox_gset:Nw
+      \vcoffin_gset_end:
+      \vbox_gset_end: \coffin_greset_poles:N \@@_gset_pole:Nnn
+  }
+\cs_generate_variant:Nn \vcoffin_gset:Nnw { c }
+\cs_new_protected:Npn \@@_set_vertical:NnNNNNNw #1#2#3#4#5#6#7
+  {
+    \@@_if_exist:NT #1
+      {
+        #3 #1
+          \dim_set:Nn \tex_hsize:D {#2}
+          \@@_set_vertical_aux:
+          \cs_set_protected:Npn #4
+            {
+              #5
+              #6 #1
+              \vbox_set_top:Nn \l_@@_internal_box { \vbox_unpack:N #1 }
+              #7 #1 { T }
+                {
+                  { 0pt }
+                  {
+                    \dim_eval:n
+                      { \box_ht:N #1 - \box_ht:N \l_@@_internal_box }
+                  }
+                  { 1000pt }
+                  { 0pt }
+                }
+              \box_clear:N \l_@@_internal_box
+            }
+      }
+  }
+\cs_new_protected:Npn \vcoffin_set_end: { }
+\cs_new_protected:Npn \vcoffin_gset_end: { }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \coffin_set_eq:NN, \coffin_set_eq:Nc,
+%     \coffin_set_eq:cN, \coffin_set_eq:cc,
+%     \coffin_gset_eq:NN, \coffin_gset_eq:Nc,
+%     \coffin_gset_eq:cN, \coffin_gset_eq:cc
+%   }
+%   Setting two coffins equal is just a wrapper around other functions.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_set_eq:NN #1#2
+  {
+    \@@_if_exist:NT #1
+      {
+        \box_set_eq:NN #1 #2
+        \prop_set_eq:cc { coffin ~ \@@_to_value:N #1 ~ corners }
+          { coffin ~ \@@_to_value:N #2 ~ corners }
+        \prop_set_eq:cc { coffin ~ \@@_to_value:N #1 ~ poles }
+          { coffin ~ \@@_to_value:N #2 ~ poles }
+      }
+  }
+\cs_generate_variant:Nn \coffin_set_eq:NN { c , Nc , cc }
+\cs_new_protected:Npn \coffin_gset_eq:NN #1#2
+  {
+    \@@_if_exist:NT #1
+      {
+        \box_gset_eq:NN #1 #2
+        \prop_gset_eq:cc { coffin ~ \@@_to_value:N #1 ~ corners }
+          { coffin ~ \@@_to_value:N #2 ~ corners }
+        \prop_gset_eq:cc { coffin ~ \@@_to_value:N #1 ~ poles }
+          { coffin ~ \@@_to_value:N #2 ~ poles }
+      }
+  }
+\cs_generate_variant:Nn \coffin_gset_eq:NN { c , Nc , cc }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\c_empty_coffin}
+% \begin{variable}{\l_@@_aligned_coffin}
+% \begin{variable}{\l_@@_aligned_internal_coffin}
+%   Special coffins: these cannot be set up earlier as they need
+%   \cs{coffin_new:N}. The empty coffin is set as a box as the full
+%   coffin-setting system needs some material which is not yet available.
+%   The empty coffin is creted entirely by hand: not everything is in place
+%   yet.
+%    \begin{macrocode}
+\coffin_new:N \c_empty_coffin
+\coffin_new:N \l_@@_aligned_coffin
+\coffin_new:N \l_@@_aligned_internal_coffin
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}
+%   {\l_tmpa_coffin, \l_tmpb_coffin, \g_tmpa_coffin, \g_tmpb_coffin}
+%   The usual scratch space.
+%    \begin{macrocode}
+\coffin_new:N \l_tmpa_coffin
+\coffin_new:N \l_tmpb_coffin
+\coffin_new:N \g_tmpa_coffin
+\coffin_new:N \g_tmpb_coffin
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Measuring coffins}
+%
+% \begin{macro}
+%   {
+%     \coffin_dp:N, \coffin_dp:c, \coffin_ht:N, \coffin_ht:c,
+%     \coffin_wd:N, \coffin_wd:c
+%   }
+%   Coffins are just boxes when it comes to measurement. However, semantically
+%   a separate set of functions are required.
+%    \begin{macrocode}
+\cs_new_eq:NN \coffin_dp:N \box_dp:N
+\cs_new_eq:NN \coffin_dp:c \box_dp:c
+\cs_new_eq:NN \coffin_ht:N \box_ht:N
+\cs_new_eq:NN \coffin_ht:c \box_ht:c
+\cs_new_eq:NN \coffin_wd:N \box_wd:N
+\cs_new_eq:NN \coffin_wd:c \box_wd:c
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Coffins: handle and pole management}
+%
+% \begin{macro}{\@@_get_pole:NnN}
+%   A simple wrapper around the recovery of a coffin pole, with some
+%   error checking and recovery built-in.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_get_pole:NnN #1#2#3
+  {
+    \prop_get:cnNF
+      { coffin ~ \@@_to_value:N #1 ~ poles } {#2} #3
+      {
+        \msg_error:nnee { coffin } { unknown-pole }
+          { \exp_not:n {#2} } { \token_to_str:N #1 }
+        \tl_set:Nn #3 { { 0pt } { 0pt } { 0pt } { 0pt } }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_reset_structure:N, \@@_greset_structure:N}
+%   Resetting the structure is a simple copy job.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_reset_structure:N #1
+  {
+    \prop_set_eq:cN { coffin ~ \@@_to_value:N #1 ~ corners }
+      \c_@@_corners_prop
+    \prop_set_eq:cN { coffin ~ \@@_to_value:N #1 ~ poles }
+      \c_@@_poles_prop
+  }
+\cs_new_protected:Npn \@@_greset_structure:N #1
+  {
+    \prop_gset_eq:cN { coffin ~ \@@_to_value:N #1 ~ corners }
+      \c_@@_corners_prop
+    \prop_gset_eq:cN { coffin ~ \@@_to_value:N #1 ~ poles }
+      \c_@@_poles_prop
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \coffin_set_horizontal_pole:Nnn, \coffin_set_horizontal_pole:cnn,
+%     \coffin_gset_horizontal_pole:Nnn, \coffin_gset_horizontal_pole:cnn
+%   }
+% \begin{macro}{\@@_set_horizontal_pole:NnnN}
+% \begin{macro}
+%   {
+%     \coffin_set_vertical_pole:Nnn, \coffin_set_vertical_pole:cnn,
+%     \coffin_gset_vertical_pole:Nnn, \coffin_gset_vertical_pole:cnn
+%   }
+% \begin{macro}{\@@_set_vertical_pole:NnnN}
+% \begin{macro}{\@@_set_pole:Nnn, \@@_gset_pole:Nnn}
+%   Setting the pole of a coffin at the user/designer level requires a
+%   bit more care. The idea here is to provide a reasonable interface to
+%   the system, then to do the setting with full expansion. The
+%   three-argument version is used internally to do a direct setting.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_set_horizontal_pole:Nnn #1#2#3
+  { \@@_set_horizontal_pole:NnnN #1 {#2} {#3} \prop_put:cne }
+\cs_generate_variant:Nn \coffin_set_horizontal_pole:Nnn { c }
+\cs_new_protected:Npn \coffin_gset_horizontal_pole:Nnn #1#2#3
+  { \@@_set_horizontal_pole:NnnN #1 {#2} {#3} \prop_gput:cne }
+\cs_generate_variant:Nn \coffin_gset_horizontal_pole:Nnn { c }
+\cs_new_protected:Npn \@@_set_horizontal_pole:NnnN #1#2#3#4
+  {
+    \@@_if_exist:NT #1
+      {
+        #4 { coffin ~ \@@_to_value:N #1 ~ poles }
+          {#2}
+          {
+            { 0pt } { \dim_eval:n {#3} }
+            { 1000pt } { 0pt }
+          }
+      }
+  }
+\cs_new_protected:Npn \coffin_set_vertical_pole:Nnn #1#2#3
+  { \@@_set_vertical_pole:NnnN #1 {#2} {#3} \prop_put:cne }
+\cs_generate_variant:Nn \coffin_set_vertical_pole:Nnn { c }
+\cs_new_protected:Npn \coffin_gset_vertical_pole:Nnn #1#2#3
+  { \@@_set_vertical_pole:NnnN #1 {#2} {#3} \prop_gput:cne }
+  \cs_generate_variant:Nn \coffin_gset_vertical_pole:Nnn { c }
+\cs_new_protected:Npn \@@_set_vertical_pole:NnnN #1#2#3#4
+  {
+    \@@_if_exist:NT #1
+      {
+        #4 { coffin ~ \@@_to_value:N #1 ~ poles }
+          {#2}
+          {
+            { \dim_eval:n {#3} } { 0pt }
+            { 0pt } { 1000pt }
+          }
+      }
+  }
+\cs_new_protected:Npn \@@_set_pole:Nnn #1#2#3
+  {
+    \prop_put:cne { coffin ~ \@@_to_value:N #1 ~ poles }
+      {#2} {#3}
+  }
+\cs_new_protected:Npn \@@_gset_pole:Nnn #1#2#3
+  {
+    \prop_gput:cne { coffin ~ \@@_to_value:N #1 ~ poles }
+      {#2} {#3}
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\coffin_reset_poles:N, \coffin_greset_poles:N}
+%   Simple shortcuts.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_reset_poles:N #1
+  {
+    \@@_reset_structure:N #1
+    \@@_update_corners:N #1
+    \@@_update_poles:N #1
+  }
+\cs_new_protected:Npn \coffin_greset_poles:N #1
+  {
+    \@@_greset_structure:N #1
+    \@@_gupdate_corners:N #1
+    \@@_gupdate_poles:N #1
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_update_corners:N, \@@_gupdate_corners:N}
+% \begin{macro}{\@@_update_corners:NN}
+% \begin{macro}{\@@_update_corners:NNN}
+%   Updating the corners of a coffin is straight-forward as at this stage
+%   there can be no rotation. So the corners of the content are just those
+%   of the underlying \TeX{} box.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_update_corners:N #1
+  { \@@_update_corners:NN #1 \prop_put:Nne }
+\cs_new_protected:Npn \@@_gupdate_corners:N #1
+  { \@@_update_corners:NN #1 \prop_gput:Nne }
+\cs_new_protected:Npn \@@_update_corners:NN #1#2
+  {
+    \exp_args:Nc \@@_update_corners:NNN
+      { coffin ~ \@@_to_value:N #1 ~ corners }
+      #1 #2
+  }
+\cs_new_protected:Npn \@@_update_corners:NNN #1#2#3
+  {
+    #3 #1
+      { tl }
+      { { 0pt } { \dim_eval:n { \box_ht:N #2 } } }
+    #3 #1
+      { tr }
+      {
+        { \dim_eval:n { \box_wd:N #2 } }
+        { \dim_eval:n { \box_ht:N #2 } }
+      }
+    #3 #1
+      { bl }
+      { { 0pt } { \dim_eval:n { -\box_dp:N #2 } } }
+    #3 #1
+      { br }
+      {
+        { \dim_eval:n { \box_wd:N #2 } }
+        { \dim_eval:n { -\box_dp:N #2 } }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_update_poles:N, \@@_gupdate_poles:N}
+% \begin{macro}{\@@_update_poles:NN}
+% \begin{macro}{\@@_update_poles:NNN}
+%   This function is called when a coffin is set, and updates the poles to
+%   reflect the nature of size of the box. Thus this function only alters
+%   poles where the default position is dependent on the size of the box.
+%   It also does not set poles which are relevant only to vertical
+%   coffins.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_update_poles:N #1
+  { \@@_update_poles:NN #1 \prop_put:Nne }
+\cs_new_protected:Npn \@@_gupdate_poles:N #1
+  { \@@_update_poles:NN #1 \prop_gput:Nne }
+\cs_new_protected:Npn \@@_update_poles:NN #1#2
+  {
+    \exp_args:Nc \@@_update_poles:NNN
+      { coffin ~ \@@_to_value:N #1 ~ poles }
+      #1 #2
+  }
+\cs_new_protected:Npn \@@_update_poles:NNN #1#2#3
+  {
+    #3 #1 { hc }
+      {
+        { \dim_eval:n { 0.5 \box_wd:N #2 } }
+        { 0pt } { 0pt } { 1000pt }
+      }
+    #3 #1 { r }
+      {
+        { \dim_eval:n { \box_wd:N #2 } }
+        { 0pt } { 0pt } { 1000pt }
+      }
+    #3 #1 { vc }
+      {
+        { 0pt }
+        { \dim_eval:n { ( \box_ht:N #2 - \box_dp:N #2 ) / 2 } }
+        { 1000pt }
+        { 0pt }
+      }
+    #3 #1 { t }
+      {
+        { 0pt }
+        { \dim_eval:n { \box_ht:N #2 } }
+        { 1000pt }
+        { 0pt }
+      }
+    #3 #1 { b }
+      {
+        { 0pt }
+        { \dim_eval:n { -\box_dp:N #2 } }
+        { 1000pt }
+        { 0pt }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Coffins: calculation of pole intersections}
+%
+% \begin{macro}{\@@_calculate_intersection:Nnn}
+% \begin{macro}{\@@_calculate_intersection:nnnnnnnn}
+% \begin{macro}{\@@_calculate_intersection:nnnnnn}
+%   The lead off in finding intersections is to recover the two poles
+%   and then hand off to the auxiliary for the actual calculation. There
+%   may of course not be an intersection, for which an error trap is
+%   needed.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_calculate_intersection:Nnn #1#2#3
+  {
+    \@@_get_pole:NnN #1 {#2} \l_@@_pole_a_tl
+    \@@_get_pole:NnN #1 {#3} \l_@@_pole_b_tl
+    \bool_set_false:N \l_@@_error_bool
+    \exp_last_two_unbraced:Noo
+      \@@_calculate_intersection:nnnnnnnn
+        \l_@@_pole_a_tl \l_@@_pole_b_tl
+    \bool_if:NT \l_@@_error_bool
+      {
+        \msg_error:nn { coffin } { no-pole-intersection }
+        \dim_zero:N \l_@@_x_dim
+        \dim_zero:N \l_@@_y_dim
+      }
+  }
+%    \end{macrocode}
+%   The two poles passed here each have four values (as dimensions),
+%   ($a$, $b$, $c$, $d$) and
+%   ($a'$, $b'$, $c'$, $d'$). These are arguments
+%   $1$--$4$ and $5$--$8$, respectively. In both
+%   cases $a$ and  $b$ are the co-ordinates of a point on the
+%   pole and $c$ and $d$ define the direction of the pole. Finding
+%   the intersection depends on the directions of the poles, which are
+%   given by $d / c$ and $d' / c'$. However, if one of the poles
+%   is either horizontal or vertical then one or more of $c$, $d$,
+%   $c'$ and $d'$ are zero and a special case is needed.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_calculate_intersection:nnnnnnnn
+  #1#2#3#4#5#6#7#8
+  {
+    \dim_compare:nNnTF {#3} = \c_zero_dim
+%    \end{macrocode}
+%   The case where the first pole is vertical.  So the $x$-component
+%   of the interaction is at $a$. There is then a test on the
+%   second pole: if it is also vertical then there is an error.
+%    \begin{macrocode}
+      {
+        \dim_set:Nn \l_@@_x_dim {#1}
+        \dim_compare:nNnTF {#7} = \c_zero_dim
+          { \bool_set_true:N \l_@@_error_bool }
+%    \end{macrocode}
+%   The second pole may still be horizontal, in which case the
+%   $y$-component of the intersection is $b'$. If not,
+%   \[
+%     y = \frac{d'}{c'} \left ( a - a' \right ) + b'
+%   \]
+%   with the $x$-component already known to be |#1|.
+%    \begin{macrocode}
+          {
+            \dim_set:Nn \l_@@_y_dim
+              {
+                \dim_compare:nNnTF {#8} = \c_zero_dim
+                  {#6}
+                  {
+                    \fp_to_dim:n
+                      {
+                          ( \dim_to_fp:n {#8} / \dim_to_fp:n {#7} )
+                        * ( \dim_to_fp:n {#1} - \dim_to_fp:n {#5} )
+                        + \dim_to_fp:n {#6}
+                      }
+                  }
+              }
+          }
+      }
+%    \end{macrocode}
+%   If the first pole is not vertical then it may be horizontal. If so,
+%   then the procedure is essentially the same as that already done but
+%   with the $x$- and $y$-components interchanged.
+%    \begin{macrocode}
+      {
+        \dim_compare:nNnTF {#4} = \c_zero_dim
+          {
+            \dim_set:Nn \l_@@_y_dim {#2}
+            \dim_compare:nNnTF {#8} = { \c_zero_dim }
+              { \bool_set_true:N \l_@@_error_bool }
+              {
+%    \end{macrocode}
+%   Now we deal with the case where the second pole may be vertical, or
+%   if not we have
+%   \[
+%     x = \frac{c'}{d'} \left ( b - b' \right ) + a'
+%   \]
+%   which is again handled by the same auxiliary.
+%    \begin{macrocode}
+                \dim_set:Nn \l_@@_x_dim
+                  {
+                    \dim_compare:nNnTF {#7} = \c_zero_dim
+                      {#5}
+                      {
+                        \fp_to_dim:n
+                          {
+                              ( \dim_to_fp:n {#7} / \dim_to_fp:n {#8} )
+                            * ( \dim_to_fp:n {#4} - \dim_to_fp:n {#6} )
+                            + \dim_to_fp:n {#5}
+                          }
+                      }
+                  }
+              }
+          }
+%    \end{macrocode}
+%   The first pole is neither horizontal nor vertical. To avoid even
+%   more complexity, we now work out both slopes and pass to an auxiliary.
+%    \begin{macrocode}
+          {
+            \use:e
+              {
+                \@@_calculate_intersection:nnnnnn
+                  { \dim_to_fp:n {#4} / \dim_to_fp:n {#3} }
+                  { \dim_to_fp:n {#8} / \dim_to_fp:n {#7} }
+              }
+                {#1} {#2} {#5} {#6}
+          }
+      }
+  }
+%    \end{macrocode}
+%   Assuming the two poles are not parallel, then the intersection point is
+%   found in two steps. First we find the $x$-value with
+%   \[
+%     x = \frac { sa - s'a'  - b + b' }{ s - s' }
+%   \]
+%   and then finding the $y$-value with
+%   \[
+%     y = s ( x - a ) + b
+%   \]
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_calculate_intersection:nnnnnn #1#2#3#4#5#6
+  {
+    \fp_compare:nNnTF {#1} = {#2}
+      { \bool_set_true:N \l_@@_error_bool }
+      {
+        \dim_set:Nn \l_@@_x_dim
+          {
+            \fp_to_dim:n
+              {
+                (
+                    #1 * \dim_to_fp:n {#3}
+                  - #2 * \dim_to_fp:n {#5}
+                  - \dim_to_fp:n {#4}
+                  + \dim_to_fp:n {#6}
+                )
+                /
+                ( #1 - #2 )
+              }
+          }
+        \dim_set:Nn \l_@@_y_dim
+          {
+            \fp_to_dim:n
+              {
+                  #1 * ( \l_@@_x_dim - \dim_to_fp:n {#3} )
+                + \dim_to_fp:n {#4}
+              }
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Affine transformations}
+%
+% \begin{variable}{\l_@@_sin_fp}
+% \begin{variable}{\l_@@_cos_fp}
+%   Used for rotations to get the sine and cosine values.
+%    \begin{macrocode}
+\fp_new:N \l_@@_sin_fp
+\fp_new:N \l_@@_cos_fp
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_bounding_prop}
+%   A property list for the bounding box of a coffin. This is only needed
+%   during the rotation, so there is just the one.
+%    \begin{macrocode}
+\prop_new:N \l_@@_bounding_prop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_corners_prop, \l_@@_poles_prop}
+%   Used to avoid needing to track scope for intermediate steps.
+%    \begin{macrocode}
+\prop_new:N \l_@@_corners_prop
+\prop_new:N \l_@@_poles_prop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_bounding_shift_dim}
+%   The shift of the bounding box of a coffin from the real content.
+%    \begin{macrocode}
+\dim_new:N \l_@@_bounding_shift_dim
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_left_corner_dim}
+% \begin{variable}{\l_@@_right_corner_dim}
+% \begin{variable}{\l_@@_bottom_corner_dim}
+% \begin{variable}{\l_@@_top_corner_dim}
+%   These are used to hold maxima for the various corner values: these
+%   thus define the minimum size of the bounding box after rotation.
+%    \begin{macrocode}
+\dim_new:N \l_@@_left_corner_dim
+\dim_new:N \l_@@_right_corner_dim
+\dim_new:N \l_@@_bottom_corner_dim
+\dim_new:N \l_@@_top_corner_dim
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+%
+% \begin{macro}
+%   {
+%     \coffin_rotate:Nn, \coffin_rotate:cn,
+%     \coffin_grotate:Nn, \coffin_grotate:cn
+%   }
+% \begin{macro}{\@@_rotate:NnNNN}
+%   Rotating a coffin requires several steps which can be conveniently
+%   run together. The sine and cosine of the angle in degrees are
+%   computed.  This is then used to set \cs{l_@@_sin_fp} and
+%   \cs{l_@@_cos_fp}, which are carried through unchanged for the rest
+%   of the procedure.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_rotate:Nn #1#2
+  { \@@_rotate:NnNNN #1 {#2} \box_rotate:Nn \prop_set_eq:cN \hbox_set:Nn }
+\cs_generate_variant:Nn \coffin_rotate:Nn { c }
+\cs_new_protected:Npn \coffin_grotate:Nn #1#2
+  { \@@_rotate:NnNNN #1 {#2} \box_grotate:Nn \prop_gset_eq:cN \hbox_gset:Nn }
+\cs_generate_variant:Nn \coffin_grotate:Nn { c }
+\cs_new_protected:Npn \@@_rotate:NnNNN #1#2#3#4#5
+  {
+    \fp_set:Nn \l_@@_sin_fp { sind ( #2 ) }
+    \fp_set:Nn \l_@@_cos_fp { cosd ( #2 ) }
+%    \end{macrocode}
+%   Use a local copy of the property lists to avoid needing to pass the
+%   name and scope around.
+%    \begin{macrocode}
+    \prop_set_eq:Nc \l_@@_corners_prop
+      { coffin ~ \@@_to_value:N #1 ~ corners }
+    \prop_set_eq:Nc \l_@@_poles_prop
+      { coffin ~ \@@_to_value:N #1 ~ poles }
+%    \end{macrocode}
+%   The corners and poles of the coffin can now be rotated around the
+%    origin. This is best achieved using mapping functions.
+%    \begin{macrocode}
+    \prop_map_inline:Nn \l_@@_corners_prop
+      { \@@_rotate_corner:Nnnn #1 {##1} ##2 }
+    \prop_map_inline:Nn \l_@@_poles_prop
+      { \@@_rotate_pole:Nnnnnn #1 {##1} ##2 }
+%    \end{macrocode}
+%   The bounding box of the coffin needs to be rotated, and to do this
+%   the corners have to be found first. They are then rotated in the same
+%   way as the corners of the coffin material itself.
+%    \begin{macrocode}
+    \@@_set_bounding:N #1
+    \prop_map_inline:Nn \l_@@_bounding_prop
+      { \@@_rotate_bounding:nnn {##1} ##2 }
+%    \end{macrocode}
+%   At this stage, there needs to be a calculation to find where the
+%   corners of the content and the box itself will end up.
+%    \begin{macrocode}
+    \@@_find_corner_maxima:N #1
+    \@@_find_bounding_shift:
+    #3 #1 {#2}
+%    \end{macrocode}
+%   The correction of the box position itself takes place here. The idea
+%   is that the bounding box for a coffin is tight up to the content, and
+%   has the reference point at the bottom-left. The $x$-direction is
+%   handled by moving the content by the difference in the positions of
+%   the bounding box and the content left edge. The $y$-direction is
+%   dealt with by moving the box down by any depth it has acquired. The
+%   internal box is used here to allow for the next step.
+%    \begin{macrocode}
+    \hbox_set:Nn \l_@@_internal_box
+      {
+        \__kernel_kern:n
+            { \l_@@_bounding_shift_dim - \l_@@_left_corner_dim }
+        \box_move_down:nn { \l_@@_bottom_corner_dim }
+          { \box_use:N #1 }
+      }
+%    \end{macrocode}
+%   If there have been any previous rotations then the size of the
+%   bounding box will be bigger than the contents. This can be corrected
+%   easily by setting the size of the box to the height and width of the
+%   content. As this operation requires setting box dimensions and these
+%   transcend grouping, the safe way to do this is to use the internal box
+%   and to reset the result into the target box.
+%    \begin{macrocode}
+    \box_set_ht:Nn \l_@@_internal_box
+      { \l_@@_top_corner_dim - \l_@@_bottom_corner_dim }
+    \box_set_dp:Nn \l_@@_internal_box { 0pt }
+    \box_set_wd:Nn \l_@@_internal_box
+      { \l_@@_right_corner_dim - \l_@@_left_corner_dim }
+    #5 #1 { \box_use_drop:N \l_@@_internal_box }
+%    \end{macrocode}
+%   The final task is to move the poles and corners such that they are
+%   back in alignment with the box reference point.
+%    \begin{macrocode}
+    \prop_map_inline:Nn \l_@@_corners_prop
+      { \@@_shift_corner:Nnnn #1 {##1} ##2 }
+    \prop_map_inline:Nn \l_@@_poles_prop
+      { \@@_shift_pole:Nnnnnn #1 {##1} ##2 }
+%    \end{macrocode}
+%   Update the coffin data.
+%    \begin{macrocode}
+    #4 { coffin ~ \@@_to_value:N #1 ~ corners }
+      \l_@@_corners_prop
+    #4 { coffin ~ \@@_to_value:N #1 ~ poles }
+      \l_@@_poles_prop
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_set_bounding:N}
+%   The bounding box corners for a coffin are easy enough to find: this
+%   is the same code as for the corners of the material itself, but
+%   using a dedicated property list.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_set_bounding:N #1
+  {
+    \prop_put:Nne \l_@@_bounding_prop { tl }
+      { { 0pt } { \dim_eval:n { \box_ht:N #1 } } }
+    \prop_put:Nne \l_@@_bounding_prop { tr }
+      {
+        { \dim_eval:n { \box_wd:N #1 } }
+        { \dim_eval:n { \box_ht:N #1 } }
+      }
+    \dim_set:Nn \l_@@_internal_dim { -\box_dp:N #1 }
+    \prop_put:Nne \l_@@_bounding_prop { bl }
+      { { 0pt } { \dim_use:N \l_@@_internal_dim } }
+    \prop_put:Nne \l_@@_bounding_prop { br }
+      {
+        { \dim_eval:n { \box_wd:N #1 } }
+        { \dim_use:N \l_@@_internal_dim }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_rotate_bounding:nnn}
+% \begin{macro}{\@@_rotate_corner:Nnnn}
+%   Rotating the position of the corner of the coffin is just a case
+%   of treating this as a vector from the reference point. The same
+%   treatment is used for the corners of the material itself and the
+%   bounding box.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_bounding:nnn #1#2#3
+  {
+    \@@_rotate_vector:nnNN {#2} {#3} \l_@@_x_dim \l_@@_y_dim
+    \prop_put:Nne \l_@@_bounding_prop {#1}
+      { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
+  }
+\cs_new_protected:Npn \@@_rotate_corner:Nnnn #1#2#3#4
+  {
+    \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
+    \prop_put:Nne \l_@@_corners_prop {#2}
+      { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_rotate_pole:Nnnnnn}
+%   Rotating a single pole simply means shifting the co-ordinate of
+%   the pole and its direction. The rotation here is about the bottom-left
+%   corner of the coffin.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_pole:Nnnnnn #1#2#3#4#5#6
+  {
+    \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
+    \@@_rotate_vector:nnNN {#5} {#6}
+      \l_@@_x_prime_dim \l_@@_y_prime_dim
+    \prop_put:Nne \l_@@_poles_prop {#2}
+      {
+        { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim }
+        { \dim_use:N \l_@@_x_prime_dim }
+        { \dim_use:N \l_@@_y_prime_dim }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_rotate_vector:nnNN}
+%   A rotation function, which needs only an input vector (as dimensions)
+%   and an output space. The values \cs{l_@@_cos_fp} and
+%   \cs{l_@@_sin_fp} should previously have been set up correctly.
+%   Working this way means that the floating point work is kept to a
+%   minimum: for any given rotation the sin and cosine values do no
+%   change, after all.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_vector:nnNN #1#2#3#4
+  {
+    \dim_set:Nn #3
+      {
+        \fp_to_dim:n
+          {
+              \dim_to_fp:n {#1} * \l_@@_cos_fp
+            - \dim_to_fp:n {#2} * \l_@@_sin_fp
+          }
+      }
+    \dim_set:Nn #4
+      {
+        \fp_to_dim:n
+          {
+              \dim_to_fp:n {#1} * \l_@@_sin_fp
+            + \dim_to_fp:n {#2} * \l_@@_cos_fp
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_find_corner_maxima:N}
+% \begin{macro}{\@@_find_corner_maxima_aux:nn}
+%   The idea here is to find the extremities of the content of the
+%   coffin. This is done by looking for the smallest values for the bottom
+%   and left corners, and the largest values for the top and right
+%   corners. The values start at the maximum dimensions so that the
+%   case where all are positive or all are negative works out correctly.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_find_corner_maxima:N #1
+  {
+    \dim_set:Nn \l_@@_top_corner_dim   { -\c_max_dim }
+    \dim_set:Nn \l_@@_right_corner_dim { -\c_max_dim }
+    \dim_set:Nn \l_@@_bottom_corner_dim { \c_max_dim }
+    \dim_set:Nn \l_@@_left_corner_dim   { \c_max_dim }
+    \prop_map_inline:Nn \l_@@_corners_prop
+      { \@@_find_corner_maxima_aux:nn ##2 }
+  }
+\cs_new_protected:Npn \@@_find_corner_maxima_aux:nn #1#2
+  {
+    \dim_set:Nn \l_@@_left_corner_dim
+      { \dim_min:nn { \l_@@_left_corner_dim } {#1} }
+    \dim_set:Nn \l_@@_right_corner_dim
+      { \dim_max:nn { \l_@@_right_corner_dim } {#1} }
+    \dim_set:Nn \l_@@_bottom_corner_dim
+      { \dim_min:nn { \l_@@_bottom_corner_dim } {#2} }
+    \dim_set:Nn \l_@@_top_corner_dim
+      { \dim_max:nn { \l_@@_top_corner_dim } {#2} }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_find_bounding_shift:}
+% \begin{macro}{\@@_find_bounding_shift_aux:nn}
+%   The approach to finding the shift for the bounding box is similar to
+%   that for the corners. However, there is only one value needed here and
+%   a fixed input property list, so things are a bit clearer.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_find_bounding_shift:
+  {
+    \dim_set:Nn \l_@@_bounding_shift_dim { \c_max_dim }
+    \prop_map_inline:Nn \l_@@_bounding_prop
+      { \@@_find_bounding_shift_aux:nn ##2 }
+  }
+\cs_new_protected:Npn \@@_find_bounding_shift_aux:nn #1#2
+  {
+    \dim_set:Nn \l_@@_bounding_shift_dim
+      { \dim_min:nn { \l_@@_bounding_shift_dim } {#1} }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_shift_corner:Nnnn}
+% \begin{macro}{\@@_shift_pole:Nnnnnn}
+%   Shifting the corners and poles of a coffin means subtracting the
+%   appropriate values from the $x$- and $y$-components. For
+%   the poles, this means that the direction vector is unchanged.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_shift_corner:Nnnn #1#2#3#4
+  {
+    \prop_put:Nne \l_@@_corners_prop {#2}
+      {
+        { \dim_eval:n { #3 - \l_@@_left_corner_dim } }
+        { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } }
+      }
+  }
+\cs_new_protected:Npn \@@_shift_pole:Nnnnnn #1#2#3#4#5#6
+  {
+    \prop_put:Nne \l_@@_poles_prop {#2}
+      {
+        { \dim_eval:n { #3 - \l_@@_left_corner_dim } }
+        { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } }
+        {#5} {#6}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_scale_x_fp}
+% \begin{variable}{\l_@@_scale_y_fp}
+%   Storage for the scaling factors in $x$ and $y$, respectively.
+%    \begin{macrocode}
+\fp_new:N \l_@@_scale_x_fp
+\fp_new:N \l_@@_scale_y_fp
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_scaled_total_height_dim}
+% \begin{variable}{\l_@@_scaled_width_dim}
+%   When scaling, the values given have to be turned into absolute values.
+%    \begin{macrocode}
+\dim_new:N \l_@@_scaled_total_height_dim
+\dim_new:N \l_@@_scaled_width_dim
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{macro}
+%   {
+%     \coffin_resize:Nnn, \coffin_resize:cnn,
+%     \coffin_gresize:Nnn, \coffin_gresize:cnn
+%   }
+% \begin{macro}{\@@_resize:NnnNN}
+%   Resizing a coffin begins by setting up the user-friendly names for
+%   the dimensions of the coffin box. The new sizes are then turned into
+%   scale factor. This is the same operation as takes place for the
+%   underlying box, but that operation is grouped and so the same
+%   calculation is done here.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_resize:Nnn #1#2#3
+  {
+    \@@_resize:NnnNN #1 {#2} {#3}
+      \box_resize_to_wd_and_ht_plus_dp:Nnn
+      \prop_set_eq:cN
+  }
+\cs_generate_variant:Nn \coffin_resize:Nnn { c }
+\cs_new_protected:Npn \coffin_gresize:Nnn #1#2#3
+  {
+    \@@_resize:NnnNN #1 {#2} {#3}
+      \box_gresize_to_wd_and_ht_plus_dp:Nnn
+      \prop_gset_eq:cN
+  }
+\cs_generate_variant:Nn \coffin_gresize:Nnn { c }
+\cs_new_protected:Npn \@@_resize:NnnNN #1#2#3#4#5
+  {
+    \fp_set:Nn \l_@@_scale_x_fp
+      { \dim_to_fp:n {#2} / \dim_to_fp:n { \coffin_wd:N #1 } }
+    \fp_set:Nn \l_@@_scale_y_fp
+      {
+          \dim_to_fp:n {#3}
+        / \dim_to_fp:n { \coffin_ht:N #1 + \coffin_dp:N #1 }
+      }
+    #4 #1 {#2} {#3}
+    \@@_resize_common:NnnN #1 {#2} {#3} #5
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_resize_common:NnnN}
+%   The poles and corners of the coffin are scaled to the appropriate
+%   places before actually resizing the underlying box.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_resize_common:NnnN #1#2#3#4
+  {
+    \prop_set_eq:Nc \l_@@_corners_prop
+      { coffin ~ \@@_to_value:N #1 ~ corners }
+    \prop_set_eq:Nc \l_@@_poles_prop
+      { coffin ~ \@@_to_value:N #1 ~ poles }
+    \prop_map_inline:Nn \l_@@_corners_prop
+      { \@@_scale_corner:Nnnn #1 {##1} ##2 }
+    \prop_map_inline:Nn \l_@@_poles_prop
+      { \@@_scale_pole:Nnnnnn #1 {##1} ##2 }
+%    \end{macrocode}
+%   Negative $x$-scaling values place the poles in the wrong
+%   location: this is corrected here.
+%    \begin{macrocode}
+    \fp_compare:nNnT \l_@@_scale_x_fp < \c_zero_fp
+      {
+        \prop_map_inline:Nn \l_@@_corners_prop
+          { \@@_x_shift_corner:Nnnn #1 {##1} ##2 }
+        \prop_map_inline:Nn \l_@@_poles_prop
+          { \@@_x_shift_pole:Nnnnnn #1 {##1} ##2 }
+      }
+    #4 { coffin ~ \@@_to_value:N #1 ~ corners }
+      \l_@@_corners_prop
+    #4 { coffin ~ \@@_to_value:N #1 ~ poles }
+      \l_@@_poles_prop
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \coffin_scale:Nnn, \coffin_scale:cnn,
+%     \coffin_gscale:Nnn, \coffin_gscale:cnn
+%   }
+% \begin{macro}{\@@_scale:NnnNN}
+%   For scaling, the opposite calculation is done to find the new
+%   dimensions for the coffin. Only the total height is needed, as this
+%   is the shift required for corners and poles. The scaling is done
+%   the \TeX{} way as this works properly with floating point values
+%   without needing to use the \texttt{fp} module.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_scale:Nnn #1#2#3
+  { \@@_scale:NnnNN #1 {#2} {#3} \box_scale:Nnn \prop_set_eq:cN }
+\cs_generate_variant:Nn \coffin_scale:Nnn { c }
+\cs_new_protected:Npn \coffin_gscale:Nnn #1#2#3
+  { \@@_scale:NnnNN #1 {#2} {#3} \box_gscale:Nnn \prop_gset_eq:cN }
+\cs_generate_variant:Nn \coffin_gscale:Nnn { c }
+\cs_new_protected:Npn \@@_scale:NnnNN #1#2#3#4#5
+  {
+    \fp_set:Nn \l_@@_scale_x_fp {#2}
+    \fp_set:Nn \l_@@_scale_y_fp {#3}
+    #4 #1 { \l_@@_scale_x_fp } { \l_@@_scale_y_fp }
+    \dim_set:Nn \l_@@_internal_dim
+      { \coffin_ht:N #1 + \coffin_dp:N #1 }
+    \dim_set:Nn \l_@@_scaled_total_height_dim
+      { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_internal_dim }
+    \dim_set:Nn \l_@@_scaled_width_dim
+      { -\fp_abs:n { \l_@@_scale_x_fp  } \coffin_wd:N #1 }
+    \@@_resize_common:NnnN #1
+      { \l_@@_scaled_width_dim } { \l_@@_scaled_total_height_dim }
+      #5
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_scale_vector:nnNN}
+%   This functions scales a vector from the origin using the pre-set scale
+%   factors in $x$ and $y$. This is a much less complex operation
+%   than rotation, and as a result the code is a lot clearer.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_scale_vector:nnNN #1#2#3#4
+  {
+    \dim_set:Nn #3
+      { \fp_to_dim:n { \dim_to_fp:n {#1} * \l_@@_scale_x_fp } }
+    \dim_set:Nn #4
+      { \fp_to_dim:n { \dim_to_fp:n {#2} * \l_@@_scale_y_fp } }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_scale_corner:Nnnn}
+% \begin{macro}{\@@_scale_pole:Nnnnnn}
+%   Scaling both corners and poles is a simple calculation using the
+%   preceding vector scaling.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_scale_corner:Nnnn #1#2#3#4
+  {
+    \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
+    \prop_put:Nne \l_@@_corners_prop {#2}
+      { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
+  }
+\cs_new_protected:Npn \@@_scale_pole:Nnnnnn #1#2#3#4#5#6
+  {
+    \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
+    \prop_put:Nne \l_@@_poles_prop {#2}
+      {
+        { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim }
+        {#5} {#6}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_x_shift_corner:Nnnn}
+% \begin{macro}{\@@_x_shift_pole:Nnnnnn}
+%   These functions correct for the $x$ displacement that takes
+%   place with a negative horizontal scaling.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_x_shift_corner:Nnnn #1#2#3#4
+  {
+    \prop_put:Nne \l_@@_corners_prop {#2}
+      {
+        { \dim_eval:n { #3 + \box_wd:N #1 } } {#4}
+      }
+  }
+\cs_new_protected:Npn \@@_x_shift_pole:Nnnnnn #1#2#3#4#5#6
+  {
+    \prop_put:Nne \l_@@_poles_prop {#2}
+      {
+        { \dim_eval:n { #3 + \box_wd:N #1 } } {#4}
+        {#5} {#6}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Aligning and typesetting of coffins}
+%
+% \begin{macro}
+%   {
+%     \coffin_join:NnnNnnnn, \coffin_join:cnnNnnnn,
+%     \coffin_join:Nnncnnnn, \coffin_join:cnncnnnn,
+%     \coffin_gjoin:NnnNnnnn, \coffin_gjoin:cnnNnnnn,
+%     \coffin_gjoin:Nnncnnnn, \coffin_gjoin:cnncnnnn
+%   }
+% \begin{macro}{\@@_join:NnnNnnnnN}
+%   This command joins two coffins, using a horizontal and vertical pole
+%   from each coffin and making an offset between the two. The result
+%   is stored as the as a third coffin, which has all of its handles
+%   reset to standard values. First, the more basic alignment function is
+%   used to get things started.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_join:NnnNnnnn #1#2#3#4#5#6#7#8
+  {
+    \@@_join:NnnNnnnnN #1 {#2} {#3} #4 {#5} {#6} {#7} {#8}
+      \coffin_set_eq:NN
+  }
+\cs_generate_variant:Nn \coffin_join:NnnNnnnn { c , Nnnc , cnnc }
+\cs_new_protected:Npn \coffin_gjoin:NnnNnnnn #1#2#3#4#5#6#7#8
+  {
+    \@@_join:NnnNnnnnN #1 {#2} {#3} #4 {#5} {#6} {#7} {#8}
+      \coffin_gset_eq:NN
+  }
+\cs_generate_variant:Nn \coffin_gjoin:NnnNnnnn { c , Nnnc , cnnc }
+\cs_new_protected:Npn \@@_join:NnnNnnnnN #1#2#3#4#5#6#7#8#9
+  {
+    \@@_align:NnnNnnnnN
+      #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_@@_aligned_coffin
+%    \end{macrocode}
+%   Correct the placement of the reference point. If the $x$-offset
+%   is negative then the reference point of the second box is to the left
+%   of that of the first, which is corrected using a kern. On the right
+%   side the first box might stick out, which would show up if it is wider
+%   than the sum of the $x$-offset and the width of the second box.
+%   So a second kern may be needed.
+%    \begin{macrocode}
+    \hbox_set:Nn \l_@@_aligned_coffin
+      {
+        \dim_compare:nNnT { \l_@@_offset_x_dim } < \c_zero_dim
+          { \__kernel_kern:n { -\l_@@_offset_x_dim } }
+        \hbox_unpack:N \l_@@_aligned_coffin
+        \dim_set:Nn \l_@@_internal_dim
+          { \l_@@_offset_x_dim - \box_wd:N #1 + \box_wd:N #4 }
+        \dim_compare:nNnT \l_@@_internal_dim < \c_zero_dim
+          { \__kernel_kern:n { -\l_@@_internal_dim } }
+      }
+%    \end{macrocode}
+%   The coffin structure is reset, and the corners are cleared: only
+%   those from the two parent coffins are needed.
+%    \begin{macrocode}
+    \@@_reset_structure:N \l_@@_aligned_coffin
+    \prop_clear:c
+      {
+        coffin ~ \@@_to_value:N \l_@@_aligned_coffin
+        \c_space_tl corners
+      }
+    \@@_update_poles:N \l_@@_aligned_coffin
+%    \end{macrocode}
+%   The structures of the parent coffins are now transferred to the new
+%   coffin, which requires that the appropriate offsets are applied. That
+%   then depends on whether any shift was needed.
+%    \begin{macrocode}
+    \dim_compare:nNnTF \l_@@_offset_x_dim < \c_zero_dim
+      {
+        \@@_offset_poles:Nnn #1 { -\l_@@_offset_x_dim } { 0pt }
+        \@@_offset_poles:Nnn #4 { 0pt } { \l_@@_offset_y_dim }
+        \@@_offset_corners:Nnn #1 { -\l_@@_offset_x_dim } { 0pt }
+        \@@_offset_corners:Nnn #4 { 0pt } { \l_@@_offset_y_dim }
+      }
+      {
+        \@@_offset_poles:Nnn #1 { 0pt } { 0pt }
+        \@@_offset_poles:Nnn #4
+          { \l_@@_offset_x_dim } { \l_@@_offset_y_dim }
+        \@@_offset_corners:Nnn #1 { 0pt } { 0pt }
+        \@@_offset_corners:Nnn #4
+          { \l_@@_offset_x_dim } { \l_@@_offset_y_dim }
+      }
+    \@@_update_vertical_poles:NNN #1 #4 \l_@@_aligned_coffin
+    #9 #1 \l_@@_aligned_coffin
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \coffin_attach:NnnNnnnn, \coffin_attach:cnnNnnnn,
+%     \coffin_attach:Nnncnnnn, \coffin_attach:cnncnnnn,
+%     \coffin_gattach:NnnNnnnn, \coffin_gattach:cnnNnnnn,
+%     \coffin_gattach:Nnncnnnn, \coffin_gattach:cnncnnnn
+%   }
+% \begin{macro}{\@@_attach:NnnNnnnnN}
+% \begin{macro}{\@@_attach_mark:NnnNnnnn}
+%   A more simple version of the above, as it simply uses the size of the
+%   first coffin for the new one. This means that the work here is rather
+%   simplified compared to the above code. The function used when marking
+%   a position is hear also as it is similar but without the structure
+%   updates.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_attach:NnnNnnnn #1#2#3#4#5#6#7#8
+  {
+    \@@_attach:NnnNnnnnN #1 {#2} {#3} #4 {#5} {#6} {#7} {#8}
+      \coffin_set_eq:NN
+  }
+\cs_generate_variant:Nn \coffin_attach:NnnNnnnn { c , Nnnc , cnnc }
+\cs_new_protected:Npn \coffin_gattach:NnnNnnnn #1#2#3#4#5#6#7#8
+  {
+    \@@_attach:NnnNnnnnN #1 {#2} {#3} #4 {#5} {#6} {#7} {#8}
+      \coffin_gset_eq:NN
+  }
+\cs_generate_variant:Nn \coffin_gattach:NnnNnnnn { c , Nnnc , cnnc }
+\cs_new_protected:Npn \@@_attach:NnnNnnnnN #1#2#3#4#5#6#7#8#9
+  {
+    \@@_align:NnnNnnnnN
+      #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_@@_aligned_coffin
+    \box_set_ht:Nn \l_@@_aligned_coffin { \box_ht:N #1 }
+    \box_set_dp:Nn \l_@@_aligned_coffin { \box_dp:N #1 }
+    \box_set_wd:Nn \l_@@_aligned_coffin { \box_wd:N #1 }
+    \@@_reset_structure:N \l_@@_aligned_coffin
+    \prop_set_eq:cc
+      {
+        coffin ~ \@@_to_value:N \l_@@_aligned_coffin
+        \c_space_tl corners
+      }
+      { coffin ~ \@@_to_value:N #1 ~ corners }
+    \@@_update_poles:N  \l_@@_aligned_coffin
+    \@@_offset_poles:Nnn #1 { 0pt } { 0pt }
+    \@@_offset_poles:Nnn #4
+      { \l_@@_offset_x_dim } { \l_@@_offset_y_dim }
+    \@@_update_vertical_poles:NNN #1 #4 \l_@@_aligned_coffin
+    #9 #1 \l_@@_aligned_coffin
+  }
+\cs_new_protected:Npn \@@_attach_mark:NnnNnnnn #1#2#3#4#5#6#7#8
+  {
+    \@@_align:NnnNnnnnN
+      #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_@@_aligned_coffin
+    \box_set_ht:Nn \l_@@_aligned_coffin { \box_ht:N #1 }
+    \box_set_dp:Nn \l_@@_aligned_coffin { \box_dp:N #1 }
+    \box_set_wd:Nn \l_@@_aligned_coffin { \box_wd:N #1 }
+    \box_set_eq:NN #1 \l_@@_aligned_coffin
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_align:NnnNnnnnN}
+%   The internal function aligns the two coffins into a third one, but
+%   performs no corrections on the resulting coffin poles. The process
+%   begins by finding the points of intersection for the poles for each
+%   of the input coffins. Those for the first coffin are worked out after
+%   those for the second coffin, as this allows the `primed'
+%   storage area to be used for the second coffin. The `real' box
+%   offsets are then calculated, before using these to re-box the
+%   input coffins. The default poles are then set up, but the final result
+%   depends on how the bounding box is being handled.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_align:NnnNnnnnN #1#2#3#4#5#6#7#8#9
+  {
+    \@@_calculate_intersection:Nnn #4 {#5} {#6}
+    \dim_set:Nn \l_@@_x_prime_dim { \l_@@_x_dim }
+    \dim_set:Nn \l_@@_y_prime_dim { \l_@@_y_dim }
+    \@@_calculate_intersection:Nnn #1 {#2} {#3}
+    \dim_set:Nn \l_@@_offset_x_dim
+      { \l_@@_x_dim - \l_@@_x_prime_dim + #7 }
+    \dim_set:Nn \l_@@_offset_y_dim
+      { \l_@@_y_dim - \l_@@_y_prime_dim + #8 }
+    \hbox_set:Nn \l_@@_aligned_internal_coffin
+      {
+        \box_use:N #1
+        \__kernel_kern:n { -\box_wd:N #1 }
+        \__kernel_kern:n { \l_@@_offset_x_dim }
+        \box_move_up:nn { \l_@@_offset_y_dim } { \box_use:N #4 }
+      }
+    \coffin_set_eq:NN #9 \l_@@_aligned_internal_coffin
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_offset_poles:Nnn}
+% \begin{macro}{\@@_offset_pole:Nnnnnnn}
+%   Transferring structures from one coffin to another requires that the
+%   positions are updated by the offset between the two coffins. This is
+%   done by mapping over the property list of the source coffins, moving
+%   as appropriate and saving to the new coffin data structures. The
+%   test for a |-| means that the structures from the parent coffins
+%   are uniquely labelled and do not depend on the order of alignment.
+%   The pay off for this is that |-| should not be used in coffin pole
+%   or handle names, and that multiple alignments do not result in a
+%   whole set of values.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_offset_poles:Nnn #1#2#3
+  {
+    \prop_map_inline:cn { coffin ~ \@@_to_value:N #1 ~ poles }
+      { \@@_offset_pole:Nnnnnnn #1 {##1} ##2 {#2} {#3} }
+  }
+\cs_new_protected:Npn \@@_offset_pole:Nnnnnnn #1#2#3#4#5#6#7#8
+  {
+    \dim_set:Nn \l_@@_x_dim { #3 + #7 }
+    \dim_set:Nn \l_@@_y_dim { #4 + #8 }
+    \tl_if_in:nnTF {#2} { - }
+      { \tl_set:Nn \l_@@_internal_tl { {#2} } }
+      { \tl_set:Nn \l_@@_internal_tl { { #1 - #2 } } }
+    \exp_last_unbraced:NNo \@@_set_pole:Nnn \l_@@_aligned_coffin
+      { \l_@@_internal_tl }
+      {
+        { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim }
+        {#5} {#6}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_offset_corners:Nnn}
+% \begin{macro}{\@@_offset_corner:Nnnnn}
+%   Saving the offset corners of a coffin is very similar, except that
+%   there is no need to worry about naming: every corner can be saved
+%   here as order is unimportant.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_offset_corners:Nnn #1#2#3
+  {
+    \prop_map_inline:cn { coffin ~ \@@_to_value:N #1 ~ corners }
+      { \@@_offset_corner:Nnnnn #1 {##1} ##2 {#2} {#3} }
+  }
+\cs_new_protected:Npn \@@_offset_corner:Nnnnn #1#2#3#4#5#6
+  {
+    \prop_put:cne
+      {
+        coffin ~ \@@_to_value:N \l_@@_aligned_coffin
+        \c_space_tl corners
+      }
+      { #1 - #2 }
+      {
+        { \dim_eval:n { #3 + #5 } }
+        { \dim_eval:n { #4 + #6 } }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_update_vertical_poles:NNN}
+% \begin{macro}{\@@_update_T:nnnnnnnnN}
+% \begin{macro}{\@@_update_B:nnnnnnnnN}
+%   The \texttt{T} and \texttt{B} poles need to be recalculated
+%   after alignment. These functions find the larger absolute value for
+%   the poles, but this is of course only logical when the poles are
+%   horizontal.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_update_vertical_poles:NNN #1#2#3
+  {
+    \@@_get_pole:NnN #3 { #1 -T } \l_@@_pole_a_tl
+    \@@_get_pole:NnN #3 { #2 -T } \l_@@_pole_b_tl
+    \exp_last_two_unbraced:Noo \@@_update_T:nnnnnnnnN
+      \l_@@_pole_a_tl \l_@@_pole_b_tl #3
+    \@@_get_pole:NnN #3 { #1 -B } \l_@@_pole_a_tl
+    \@@_get_pole:NnN #3 { #2 -B } \l_@@_pole_b_tl
+    \exp_last_two_unbraced:Noo \@@_update_B:nnnnnnnnN
+      \l_@@_pole_a_tl \l_@@_pole_b_tl #3
+  }
+\cs_new_protected:Npn \@@_update_T:nnnnnnnnN #1#2#3#4#5#6#7#8#9
+  {
+    \dim_compare:nNnTF {#2} < {#6}
+      {
+        \@@_set_pole:Nnn #9 { T }
+          { { 0pt } {#6} { 1000pt } { 0pt } }
+      }
+      {
+        \@@_set_pole:Nnn #9 { T }
+          { { 0pt } {#2} { 1000pt } { 0pt } }
+      }
+  }
+\cs_new_protected:Npn \@@_update_B:nnnnnnnnN #1#2#3#4#5#6#7#8#9
+  {
+    \dim_compare:nNnTF {#2} < {#6}
+      {
+        \@@_set_pole:Nnn #9 { B }
+          { { 0pt } {#2}  { 1000pt } { 0pt } }
+      }
+      {
+        \@@_set_pole:Nnn #9 { B }
+          { { 0pt } {#6} { 1000pt } { 0pt } }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\c_@@_empty_coffin}
+%   An empty-but-horizontal coffin.
+%    \begin{macrocode}
+\coffin_new:N \c_@@_empty_coffin
+\tex_setbox:D \c_@@_empty_coffin = \tex_hbox:D { }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\coffin_typeset:Nnnnn, \coffin_typeset:cnnnn}
+%   Typesetting a coffin means aligning it with the current position,
+%   which is done using a coffin with no content at all. As well as aligning to
+%   the empty coffin, there is also a need to leave vertical mode, if necessary.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_typeset:Nnnnn #1#2#3#4#5
+  {
+    \mode_leave_vertical:
+    \@@_align:NnnNnnnnN \c_@@_empty_coffin { H } { l }
+      #1 {#2} {#3} {#4} {#5} \l_@@_aligned_coffin
+    \box_use_drop:N \l_@@_aligned_coffin
+  }
+\cs_generate_variant:Nn \coffin_typeset:Nnnnn { c }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Coffin diagnostics}
+%
+% \begin{variable}{\l_@@_display_coffin}
+% \begin{variable}{\l_@@_display_coord_coffin}
+% \begin{variable}{\l_@@_display_pole_coffin}
+%   Used for printing coffins with data structures attached.
+%    \begin{macrocode}
+\coffin_new:N \l_@@_display_coffin
+\coffin_new:N \l_@@_display_coord_coffin
+\coffin_new:N \l_@@_display_pole_coffin
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_display_handles_prop}
+%   This property list is used to print coffin handles at suitable
+%   positions. The offsets are expressed as multiples of the basic offset
+%   value, which therefore acts as a scale-factor.
+%    \begin{macrocode}
+\prop_new:N \l_@@_display_handles_prop
+\prop_put:Nnn \l_@@_display_handles_prop { tl }
+  { { b } { r } { -1 } { 1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { thc }
+  { { b } { hc } { 0 } { 1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { tr }
+  { { b } { l } { 1 } { 1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { vcl }
+  { { vc } { r } { -1 } { 0 } }
+\prop_put:Nnn \l_@@_display_handles_prop { vchc }
+  { { vc } { hc } { 0 } { 0 } }
+\prop_put:Nnn \l_@@_display_handles_prop { vcr }
+  { { vc } { l } { 1 } { 0 } }
+\prop_put:Nnn \l_@@_display_handles_prop { bl }
+  { { t } { r } { -1 } { -1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { bhc }
+  { { t } { hc } { 0 } { -1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { br }
+  { { t } { l } { 1 } { -1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Tl }
+  { { t } { r } { -1 } { -1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Thc }
+  { { t } { hc } { 0 } { -1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Tr }
+  { { t } { l } { 1 } { -1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Hl }
+  { { vc } { r } { -1 } { 1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Hhc }
+  { { vc } { hc } { 0 } { 1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Hr }
+  { { vc } { l } { 1 } { 1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Bl }
+  { { b } { r } { -1 } { -1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Bhc }
+  { { b } { hc } { 0 } { -1 } }
+\prop_put:Nnn \l_@@_display_handles_prop { Br }
+  { { b } { l } { 1 } { -1 } }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_display_offset_dim}
+%   The standard offset for the label from the handle position when
+%   displaying handles.
+%    \begin{macrocode}
+\dim_new:N  \l_@@_display_offset_dim
+\dim_set:Nn \l_@@_display_offset_dim { 2pt }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_display_x_dim}
+% \begin{variable}{\l_@@_display_y_dim}
+%   As the intersections of poles have to be calculated to find which
+%   ones to print, there is a need to avoid repetition. This is done
+%   by saving the intersection into two dedicated values.
+%    \begin{macrocode}
+\dim_new:N \l_@@_display_x_dim
+\dim_new:N \l_@@_display_y_dim
+%    \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_display_poles_prop}
+%   A property list for printing poles: various things need to be deleted
+%   from this to get a \enquote{nice} output.
+%    \begin{macrocode}
+\prop_new:N \l_@@_display_poles_prop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_display_font_tl}
+%   Stores the settings used to print coffin data: this keeps things
+%   flexible.
+%    \begin{macrocode}
+\tl_new:N \l_@@_display_font_tl
+\bool_lazy_and:nnT
+  { \cs_if_exist_p:N \fmtname }
+  { \str_if_eq_p:Vn \fmtname { LaTeX2e } }
+  {
+    \tl_set:Nn \l_@@_display_font_tl
+      { \sffamily \tiny }
+  }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_rule:nn}
+%   Abstract out creation of rules here until there is a higher-level interface.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_rule:nn #1#2
+  {
+    \mode_leave_vertical:
+    \hbox:n { \tex_vrule:D width #1 height #2 \scan_stop: }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\coffin_mark_handle:Nnnn, \coffin_mark_handle:cnnn}
+% \begin{macro}{\@@_mark_handle_aux:nnnnNnn}
+%   Marking a single handle is relatively easy. The standard attachment
+%   function is used, meaning that there are two calculations for the
+%   location. However, this is likely to be okay given the load expected.
+%   Contrast with the more optimised version for showing all handles which
+%   comes next.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_mark_handle:Nnnn #1#2#3#4
+  {
+    \hcoffin_set:Nn \l_@@_display_pole_coffin
+      {
+        \color_select:n {#4}
+        \@@_rule:nn { 1pt } { 1pt }
+      }
+    \@@_attach_mark:NnnNnnnn #1 {#2} {#3}
+      \l_@@_display_pole_coffin { hc } { vc } { 0pt } { 0pt }
+    \hcoffin_set:Nn \l_@@_display_coord_coffin
+      {
+        \color_select:n {#4}
+        \l_@@_display_font_tl
+        ( \tl_to_str:n { #2 , #3 } )
+      }
+    \prop_get:NnN \l_@@_display_handles_prop
+      { #2 #3 } \l_@@_internal_tl
+    \quark_if_no_value:NTF \l_@@_internal_tl
+      {
+        \prop_get:NnN \l_@@_display_handles_prop
+          { #3 #2 } \l_@@_internal_tl
+        \quark_if_no_value:NTF \l_@@_internal_tl
+          {
+            \@@_attach_mark:NnnNnnnn #1 {#2} {#3}
+              \l_@@_display_coord_coffin { l } { vc }
+                { 1pt } { 0pt }
+          }
+          {
+            \exp_last_unbraced:No \@@_mark_handle_aux:nnnnNnn
+              \l_@@_internal_tl #1 {#2} {#3}
+          }
+      }
+      {
+        \exp_last_unbraced:No \@@_mark_handle_aux:nnnnNnn
+          \l_@@_internal_tl #1 {#2} {#3}
+      }
+  }
+\cs_new_protected:Npn \@@_mark_handle_aux:nnnnNnn #1#2#3#4#5#6#7
+  {
+    \@@_attach_mark:NnnNnnnn #5 {#6} {#7}
+      \l_@@_display_coord_coffin {#1} {#2}
+      { #3 \l_@@_display_offset_dim }
+      { #4 \l_@@_display_offset_dim }
+  }
+\cs_generate_variant:Nn \coffin_mark_handle:Nnnn { c }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\coffin_display_handles:Nn, \coffin_display_handles:cn}
+% \begin{macro}{\@@_display_handles_aux:nnnnnn}
+% \begin{macro}{\@@_display_handles_aux:nnnn}
+% \begin{macro}{\@@_display_attach:Nnnnn}
+%   Printing the poles starts by removing any duplicates, for which the
+%   \texttt{H} poles is used as the definitive version for the baseline
+%   and bottom. Two loops are then used to find the combinations of
+%   handles for all of these poles. This is done such that poles are
+%   removed during the loops to avoid duplication.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_display_handles:Nn #1#2
+  {
+    \hcoffin_set:Nn \l_@@_display_pole_coffin
+      {
+        \color_select:n {#2}
+        \@@_rule:nn { 1pt } { 1pt }
+      }
+    \prop_set_eq:Nc \l_@@_display_poles_prop
+      { coffin ~ \@@_to_value:N #1 ~ poles }
+    \@@_get_pole:NnN #1 { H } \l_@@_pole_a_tl
+    \@@_get_pole:NnN #1 { T } \l_@@_pole_b_tl
+    \tl_if_eq:NNT \l_@@_pole_a_tl \l_@@_pole_b_tl
+      { \prop_remove:Nn \l_@@_display_poles_prop { T } }
+    \@@_get_pole:NnN #1 { B } \l_@@_pole_b_tl
+    \tl_if_eq:NNT \l_@@_pole_a_tl \l_@@_pole_b_tl
+      { \prop_remove:Nn \l_@@_display_poles_prop { B } }
+    \coffin_set_eq:NN \l_@@_display_coffin #1
+    \prop_map_inline:Nn \l_@@_display_poles_prop
+      {
+        \prop_remove:Nn \l_@@_display_poles_prop {##1}
+        \@@_display_handles_aux:nnnnnn {##1} ##2 {#2}
+      }
+    \box_use_drop:N \l_@@_display_coffin
+  }
+%    \end{macrocode}
+%   For each pole there is a check for an intersection, which here does
+%   not give an error if none is found. The successful values are stored
+%   and used to align the pole coffin with the main coffin for output.
+%   The positions are recovered from the preset list if available.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_display_handles_aux:nnnnnn #1#2#3#4#5#6
+  {
+    \prop_map_inline:Nn \l_@@_display_poles_prop
+      {
+        \bool_set_false:N \l_@@_error_bool
+        \@@_calculate_intersection:nnnnnnnn {#2} {#3} {#4} {#5} ##2
+        \bool_if:NF \l_@@_error_bool
+          {
+            \dim_set:Nn \l_@@_display_x_dim { \l_@@_x_dim }
+            \dim_set:Nn \l_@@_display_y_dim { \l_@@_y_dim }
+            \@@_display_attach:Nnnnn
+              \l_@@_display_pole_coffin { hc } { vc }
+              { 0pt } { 0pt }
+            \hcoffin_set:Nn \l_@@_display_coord_coffin
+              {
+                \color_select:n {#6}
+                \l_@@_display_font_tl
+                ( \tl_to_str:n { #1 , ##1 } )
+              }
+            \prop_get:NnN \l_@@_display_handles_prop
+              { #1 ##1 } \l_@@_internal_tl
+            \quark_if_no_value:NTF \l_@@_internal_tl
+              {
+                \prop_get:NnN \l_@@_display_handles_prop
+                  { ##1 #1 } \l_@@_internal_tl
+                \quark_if_no_value:NTF \l_@@_internal_tl
+                  {
+                    \@@_display_attach:Nnnnn
+                      \l_@@_display_coord_coffin { l } { vc }
+                      { 1pt } { 0pt }
+                  }
+                  {
+                    \exp_last_unbraced:No
+                      \@@_display_handles_aux:nnnn
+                      \l_@@_internal_tl
+                  }
+              }
+              {
+                \exp_last_unbraced:No \@@_display_handles_aux:nnnn
+                  \l_@@_internal_tl
+              }
+          }
+      }
+  }
+\cs_new_protected:Npn \@@_display_handles_aux:nnnn #1#2#3#4
+  {
+    \@@_display_attach:Nnnnn
+      \l_@@_display_coord_coffin {#1} {#2}
+      { #3 \l_@@_display_offset_dim }
+      { #4 \l_@@_display_offset_dim }
+  }
+\cs_generate_variant:Nn \coffin_display_handles:Nn { c }
+%    \end{macrocode}
+%   This is a dedicated version of \cs{coffin_attach:NnnNnnnn} with
+%    a hard-wired first coffin. As the intersection is already known
+%   and stored for the display coffin the code simply uses it directly,
+%   with no calculation.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_display_attach:Nnnnn #1#2#3#4#5
+  {
+    \@@_calculate_intersection:Nnn #1 {#2} {#3}
+    \dim_set:Nn \l_@@_x_prime_dim { \l_@@_x_dim }
+    \dim_set:Nn \l_@@_y_prime_dim { \l_@@_y_dim }
+    \dim_set:Nn \l_@@_offset_x_dim
+      { \l_@@_display_x_dim - \l_@@_x_prime_dim + #4 }
+    \dim_set:Nn \l_@@_offset_y_dim
+      { \l_@@_display_y_dim - \l_@@_y_prime_dim + #5 }
+    \hbox_set:Nn \l_@@_aligned_coffin
+      {
+        \box_use:N \l_@@_display_coffin
+        \__kernel_kern:n { -\box_wd:N \l_@@_display_coffin }
+        \__kernel_kern:n { \l_@@_offset_x_dim }
+        \box_move_up:nn { \l_@@_offset_y_dim } { \box_use:N #1 }
+      }
+    \box_set_ht:Nn \l_@@_aligned_coffin
+      { \box_ht:N \l_@@_display_coffin }
+    \box_set_dp:Nn \l_@@_aligned_coffin
+      { \box_dp:N \l_@@_display_coffin }
+    \box_set_wd:Nn \l_@@_aligned_coffin
+      { \box_wd:N \l_@@_display_coffin }
+    \box_set_eq:NN \l_@@_display_coffin \l_@@_aligned_coffin
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \coffin_show_structure:N, \coffin_show_structure:c,
+%     \coffin_log_structure:N, \coffin_log_structure:c,
+%     \@@_show_structure:NN
+%   }
+%   For showing the various internal structures attached to a coffin in
+%   a way that keeps things relatively readable. If there is no apparent
+%   structure then the code complains.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_show_structure:N
+  { \@@_show_structure:NN \msg_show:nneeee }
+\cs_generate_variant:Nn \coffin_show_structure:N { c }
+\cs_new_protected:Npn \coffin_log_structure:N
+  { \@@_show_structure:NN \msg_log:nneeee }
+\cs_generate_variant:Nn \coffin_log_structure:N { c }
+\cs_new_protected:Npn \@@_show_structure:NN #1#2
+  {
+    \@@_if_exist:NT #2
+      {
+        #1 { coffin } { show }
+          { \token_to_str:N #2 }
+          {
+            \iow_newline: >~ ht ~=~ \dim_eval:n { \coffin_ht:N #2 }
+            \iow_newline: >~ dp ~=~ \dim_eval:n { \coffin_dp:N #2 }
+            \iow_newline: >~ wd ~=~ \dim_eval:n { \coffin_wd:N #2 }
+          }
+          {
+            \prop_map_function:cN
+              { coffin ~ \@@_to_value:N #2 ~ poles }
+              \msg_show_item_unbraced:nn
+          }
+          { }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \coffin_show:N, \coffin_show:c, \coffin_log:N, \coffin_log:c,
+%     \coffin_show:Nnn, \coffin_show:cnn, \coffin_log:Nnn, \coffin_log:cnn,
+%     \@@_show:NNNnn
+%   }
+%   Essentially a combination of \cs{coffin_show_structure:N} and
+%   \cs{box_show:Nnn}, but we need to avoid having two prompts, so we
+%   use \cs{msg_term:nneeee} instead of
+%   \cs{msg_show:nneeee} in the |show| case.
+%    \begin{macrocode}
+\cs_new_protected:Npn \coffin_show:N #1
+  { \coffin_show:Nnn #1 \c_max_int \c_max_int }
+\cs_generate_variant:Nn \coffin_show:N { c }
+\cs_new_protected:Npn \coffin_log:N #1
+  { \coffin_log:Nnn #1 \c_max_int \c_max_int }
+\cs_generate_variant:Nn \coffin_log:N { c }
+\cs_new_protected:Npn \coffin_show:Nnn
+  { \@@_show:NNNnn \msg_term:nneeee \box_show:Nnn }
+\cs_generate_variant:Nn \coffin_show:Nnn { c }
+\cs_new_protected:Npn \coffin_log:Nnn
+  { \@@_show:NNNnn \msg_log:nneeee \box_show:Nnn }
+\cs_generate_variant:Nn \coffin_log:Nnn { c }
+\cs_new_protected:Npn \@@_show:NNNnn #1#2#3#4#5
+  {
+    \@@_if_exist:NT #3
+      {
+        \@@_show_structure:NN #1 #3
+        #2 #3 {#4} {#5}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+%    \begin{macrocode}
+\msg_new:nnnn { coffin } { no-pole-intersection }
+  { No~intersection~between~coffin~poles. }
+  {
+    LaTeX~was~asked~to~find~the~intersection~between~two~poles,~
+    but~they~do~not~have~a~unique~meeting~point:~
+    the~value~(0pt,~0pt)~will~be~used.
+  }
+\msg_new:nnnn { coffin } { unknown }
+  { Unknown~coffin~'#1'. }
+  { The~coffin~'#1'~was~never~defined. }
+\msg_new:nnnn { coffin } { unknown-pole }
+  { Pole~'#1'~unknown~for~coffin~'#2'. }
+  {
+    LaTeX~was~asked~to~find~a~typesetting~pole~for~a~coffin,~
+    but~either~the~coffin~does~not~exist~or~the~pole~name~is~wrong.
+  }
+\msg_new:nnn { coffin } { show }
+  {
+    Size~of~coffin~#1 : #2 \\
+    Poles~of~coffin~#1 : #3 .
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3coffins.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3color.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3color.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3color.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,3246 @@
+% \iffalse meta-comment
+%
+%% File: l3color.dtx
+%
+% Copyright (C) 2017-2024 The LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version.  The latest version
+% of this license is in the file
+%
+%    http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+%    https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+%   The \pkg{l3color} module\\ Color support^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \section{Color in boxes}
+%
+% Controlling the color of text in boxes requires a small number of control
+% functions, so that the boxed material uses the color at the point where
+% it is set, rather than where it is used.
+%
+% \begin{function}[added = 2011-09-03]{\color_group_begin:, \color_group_end:}
+%   \begin{syntax}
+%     \cs{color_group_begin:}
+%       \ldots
+%     \cs{color_group_end:}
+%   \end{syntax}
+%   Creates a color group: one used to \enquote{trap} color settings.
+%   This grouping is built in to for example \cs{hbox_set:Nn}.
+% \end{function}
+%
+% \begin{function}[added = 2011-09-03]{\color_ensure_current:}
+%   \begin{syntax}
+%     \cs{color_ensure_current:}
+%   \end{syntax}
+%   Ensures that material inside a box uses the foreground color
+%   at the point where the box is set, rather than that in force when the
+%   box is used. This function should usually be used within a
+%   \cs{color_group_begin:} \ldots \cs{color_group_end:} group.
+% \end{function}
+%
+% \section{Color models}
+%
+% A color \emph{model} is a way to represent sets of colors. Different models
+% are particularly suitable for different output methods, \emph{e.g.}~screen
+% or print. Parameter-based models can describe a very large number of unique
+% colors, and have a varying number of \emph{axes} which define a color
+% space. In contrast, various proprietary models are available which define
+% \emph{spot} colors (more formally separations).
+%
+% Core models are used to pass color information to output; these are
+% \enquote{native} to \pkg{l3color}. Core models use real numbers in the range
+% $[0,1]$ to represent values. The core models supported here are
+% \begin{itemize}
+%   \item \texttt{gray} Grayscale color, with a single axis running from
+%     $0$ (fully black) to $1$ (fully white)
+%   \item \texttt{rgb} Red-green-blue color, with three axes, one for each of
+%     the components
+%   \item \texttt{cmyk} Cyan-magenta-yellow-black color, with four axes, one for
+%     each of the components
+% \end{itemize}
+%
+% There are also interface models: these are convenient for users but have
+% to be manipulated before storing/passing to the backend. Interface models
+% are primarily integer-based: see below for more detail. The supported
+% interface models are
+% \begin{itemize}
+%   \item \texttt{Gray} Grayscale color, with a single axis running from
+%     $0$ (fully black) to $15$ (fully white)
+%   \item \texttt{hsb} Hue-saturation-brightness color, with three axes,all
+%     real values in the range $[0,1]$ for hue saturation and brightness
+%   \item \texttt{Hsb} Hue-saturation-brightness color, with three axes, integer
+%     in the range $[0,360]$ for hue, real values in the range $[0,1]$ for
+%     saturation and brightness
+%   \item \texttt{HSB} Hue-saturation-brightness color, with three axes, integers
+%     in the range $[0,240]$ for hue, saturation and brightness
+%   \item \texttt{HTML} HTML format representation of RGB color given as a
+%     single six-digit hexadecimal number
+%   \item \texttt{RGB} Red-green-blue color, with three axes, one for each of
+%     the components, values as integers from $0$ to $255$
+%   \item \texttt{wave} Light wavelength, a real number in the range
+%     $380$ to $780$ (nanometres)
+% \end{itemize}
+% All interface models are internally stored as |rgb|.
+%
+% Finally, there are a small number of models which are parsed to allow
+% data transfer from \pkg{xcolor} but which should not be used by end-users.
+% These are
+% \begin{itemize}
+%   \item \texttt{cmy} Cyan-magenta-yellow color with three axes, one for
+%     each of the components; converted to |cmyk|
+%   \item \texttt{tHsb} \enquote{Tuned} hue-saturation-brightness color with three
+%     axes, integer in the range $[0,360]$ for hue, real values in the range
+%     $[0,1]$ for saturation and brightness; converted to |rgb| using the
+%     standard tuning map defined by \pkg{xcolor}
+%   \item \texttt{\&spot} Spot color tint with one value; treated as a gray
+%     tint as spot color data is not available for extraction
+% \end{itemize}
+%
+% To allow parsing of data from \pkg{xcolor}, any leading model up the first
+% \texttt{:} will be discarded; the approach of selecting an internal form
+% for data is \emph{not} used in \pkg{l3color}.
+%
+% Additional models may be created to allow mixing of separation colors
+% with each other or with those from other models. See
+% Section~\ref{l3color:sec:new-models} for more detail of color support
+% for additional models.
+%
+% When color is selected by model, the \meta{values} given are specified as
+% a comma-separated list. The length of the list will therefore be determined
+% by the detail of the model involved.
+%
+% Color models (and interconversion) are complex, and more details are given
+% in the manual to the \LaTeXe{} \pkg{xcolor} package and in the
+% \emph{PostScript Language Reference Manual}, published by Addison--Wesley.
+%
+% \section{Color expressions}
+%
+% In addition to allowing specification of color by model and values,
+% \pkg{l3color} also supports color expressions. These are created
+% by combining one or more color names, with the amount of each specified
+% as a value in the range $0$--$100$. The value should be given between
+% |!| symbols in the expression. Thus for example
+% \begin{verbatim}
+%   red!50!green
+% \end{verbatim}
+% is a mixture of $50\,\%$ red and $50\,\%$ green. A trailing value is
+% interpreted as implicitly followed by |!white|, and so
+% \begin{verbatim}
+%   red!25
+% \end{verbatim}
+% specifies $25\,\%$ red mixed with $75\,\%$ white.
+%
+% Where the models for the mixed colors are different, the model of the first
+% color is used. Thus
+% \begin{verbatim}
+%   red!50!cyan
+% \end{verbatim}
+% will result in a color specification using the |rgb| model, made up of
+% $50\,\%$ red and  $50\,\%$ of cyan \emph{expressed in \texttt{rgb}}.
+% This may be important as color model interconversion is not exact.
+%
+% The one exception to the above is where the first model in an expression is
+% |gray|. In this case, the order of mixing is \enquote{swapped} internally, so
+% that for example
+% \begin{verbatim}
+%   black!50!red
+% \end{verbatim}
+% has the same result as
+% \begin{verbatim}
+%   red!50!black
+% \end{verbatim}
+% (the predefined colors |black| and |white| use the |gray| model).
+%
+% Where more than two colors are mixed in an expression, evaluation takes place
+% in a stepwise fashion. Thus in
+% \begin{verbatim}
+%   cyan!50!magenta!10!yellow
+% \end{verbatim}
+% the sub-expression
+% \begin{verbatim}
+%   cyan!50!magenta
+% \end{verbatim}
+% is first evaluated to give an intermediate color specification, before
+% the second step
+% \begin{verbatim}
+%   <intermediate>!10!yellow
+% \end{verbatim}
+% where |<intermediate>| represents this transitory calculated value.
+%
+% Within a color expression, |.| may be used to represent the color active
+% for typesetting (the current color). This allows for example
+% \begin{verbatim}
+%   .!50
+% \end{verbatim}
+% to mean a mixture of $50\,\%$ of current color with white.
+%
+% (Color expressions supported here are a subset of those provided by
+% the \LaTeXe{} \pkg{xcolor} package. At present, only such features as are
+% clearly useful have been added here.)
+%
+% \section{Named colors}
+%
+% Color names are stored in a single namespace, which makes them accessible
+% as part of color expressions. Whilst they are not reserved in a technical
+% sense, the names |black|, |white|, |red|, |green|, |blue|, |cyan|, |magenta|
+% and |yellow| have special meaning and should not be redefined. Color names
+% should be made up of letters, numbers and spaces only: other characters are
+% reserved for use in color expressions. In particular, |.| represents the
+% current color at the start of a color expression.
+%
+% \begin{function}{\color_set:nn}
+%   \begin{syntax}
+%     \cs{color_set:nn} \Arg{name} \Arg{color expression}
+%   \end{syntax}
+%   Evaluates the \meta{color expression} and stores the resulting
+%   color specification as the \meta{name}.
+% \end{function}
+%
+% \begin{function}{\color_set:nnn}
+%   \begin{syntax}
+%     \cs{color_set:nnn} \Arg{name} \Arg{model(s)} \Arg{value(s)}
+%   \end{syntax}
+%   Stores the color specification equivalent to the \meta{model(s)} and
+%   \meta{values} as the \meta{name}.
+% \end{function}
+%
+% \begin{function}{\color_set_eq:nn}
+%   \begin{syntax}
+%     \cs{color_set_eq:nn} \Arg{name1} \Arg{name2}
+%   \end{syntax}
+%   Copies the color specification in \meta{name2} to \meta{name1}. The
+%   special name |.| may be used to represent the current color, allowing
+%   it to be saved to a name.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2022-08-12]{\color_if_exist:n}
+%   \begin{syntax}
+%     \cs{color_if_exist_p:n} \Arg{name}
+%     \cs{color_if_exist:nTF} \Arg{name} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether \meta{name} is currently defined to provide a color
+%   specification.
+% \end{function}
+%
+% \begin{function}[added = 2021-05-11]{\color_show:n, \color_log:n}
+%   \begin{syntax}
+%     \cs{color_show:n} \Arg{name}
+%     \cs{color_log:n} \Arg{name}
+%   \end{syntax}
+%   Displays the color specification stored in the \meta{name} on the
+%   terminal or log file.
+% \end{function}
+%
+% \section{Selecting colors}
+%
+% General selection of color is safe when split across pages: a stack is
+% used to ensure that the correct color is re-selected on the new page.
+%
+% These commands set the current color (|.|): other more specialised functions
+% such as fill and stroke selectors do \emph{not} adjust this value.
+%
+% \begin{function}{\color_select:n}
+%   \begin{syntax}
+%     \cs{color_select:n} \Arg{color expression}
+%   \end{syntax}
+%   Parses the \meta{color expression} and then activates the resulting
+%   color specification for typeset material.
+% \end{function}
+%
+% \begin{function}{\color_select:nn}
+%   \begin{syntax}
+%     \cs{color_select:nn} \Arg{model(s)} \Arg{value(s)}
+%   \end{syntax}
+%   Activates the color specification equivalent to the \meta{model(s)} and
+%   \meta{value(s)} for typeset material.
+% \end{function}
+%
+% \begin{variable}{\l_color_fixed_model_tl}
+%   When this is set to a non-empty value, colors will be converted to
+%   the specified model when they are selected. Note that included images
+%   and similar are not influenced by this setting.
+% \end{variable}
+%
+% \section{Colors for fills and strokes}
+%
+% Colors for drawing operations and so forth are split into strokes and fills
+% (the latter may also be referred to as non-stroke color). The fill color is
+% used for text under normal circumstances. Depending on the backend, stroke
+% color may use a \emph{stack}, in which case it exhibits the same page breaking
+% behavior as general color. However, \texttt{dvips}/\texttt{dvisvgm} do not
+% support this, and so color will need to be contained within a scope, such
+% as \cs{draw_begin:}/\cs{draw_end:}.
+%
+% \begin{function}{\color_fill:n, \color_stroke:n}
+%   \begin{syntax}
+%     \cs{color_fill:n} \Arg{color expression}
+%   \end{syntax}
+%   Parses the \meta{color expression} and then activates the resulting
+%   color specification for filling or stroking.
+% \end{function}
+%
+% \begin{function}{\color_fill:nn, \color_stroke:nn}
+%   \begin{syntax}
+%     \cs{color_fill:nn} \Arg{model(s)} \Arg{value(s)}
+%   \end{syntax}
+%   Activates the color specification equivalent to the \meta{model(s)} and
+%   \meta{value(s)} for filling or stroking.
+% \end{function}
+%
+% \begin{variable}[module = color]{color.sc}
+%   When using \texttt{dvips}, this PostScript variables hold the stroke color.
+% \end{variable}
+%
+% \subsection{Coloring math mode material}
+%
+% Coloring math mode material using \cs[no-index]{color_select:nn(n)} has some restrictions
+% and often leads to spacing issues and/or poor input syntax. Avoiding generating
+% \tn{mathord} atoms whilst coloring only those parts of the input which are
+% required needs careful handling. The functionality here covers this important
+% use case.
+%
+% \begin{function}[added = 2022-01-26]{\color_math:nn, \color_math:nnn}
+%   \begin{syntax}
+%     \cs{color_math:nn} \Arg{color expression}\Arg{content}
+%     \cs{color_math:nnn} \Arg{model(s)} \Arg{value(s)} \Arg{content}
+%   \end{syntax}
+%   Works as for \cs[no-index]{color_select:n(n)} but applies color only to the math mode
+%   \meta{content}. The function does not generate a group and the \meta{content}
+%   therefore retains its math atom states. Sub/superscripts are also properly
+%   handled.
+% \end{function}
+%
+% \begin{variable}[added = 2022-01-26]{\l_color_math_active_tl}
+%   This list controls which tokens are considered as math active and
+%   should therefore be replaced by their definition during searching for
+%   sub/superscripts.
+% \end{variable}
+%
+% \section{Multiple color models}
+%
+% When selecting or setting a color with an explicit model, it is possible
+% to give values for more than one model at one time. This is particularly
+% useful where automated conversion between models does not give the desired
+% outcome. To do this, the list of models and list of values are both subdivided
+% using |/| characters (as for the similar function in \pkg{xcolor}). For
+% example, to save a color with explicit |cmyk| and |rgb| values, one could
+% use
+% \begin{verbatim}
+%   \color_set:nnn { foo } { cmyk / rgb }
+%     { 0.1 , 0.2 , 0.3 , 0.4 / 0.1, 0.2 , 0.3 }
+% \end{verbatim}
+% The manually-specified conversion will be used in preference to automated
+% calculation whenever the model(s) listed are used: both in expressions and
+% when a fixed model is active.
+%
+% Similarly, the same syntax can be applied to directly selecting a color.
+% \begin{verbatim}
+%   \color_select:nn { cmyk / rgb }
+%     { 0.1 , 0.2 , 0.3 , 0.4 / 0.1, 0.2 , 0.3 }
+% \end{verbatim}
+% Again, this list is used when a fixed model is active: the first entry is used
+% unless there is a fixed model matching one of the other entries.
+%
+% \section{Exporting color specifications}
+%
+% The major use of color expressions is in setting typesetting output, but there
+% are other places in which some form of color information is required. These
+% may need data in a different format or using a different model to the internal
+% representation. Thus a set of functions are available to export colors in
+% different formats.
+%
+% Valid export targets are
+% \begin{itemize}
+%    \item \texttt{backend} Two brace groups: the first containing the
+%      model, the second containing space-separated values appropriate
+%      for the model; this is the format required by backend functions
+%      of \pkg{expl3}
+%    \item \texttt{comma-sep-cmyk} Comma-separated cyan-magenta-yellow-black
+%      values
+%    \item \texttt{comma-sep-rgb} Comma-separated red-green-blue values
+%      suitable for use as a PDF annotation color
+%    \item \texttt{HTML} Uppercase two-digit hexadecimal values, expressing
+%      a red-green-blue color; the digits are \emph{not} separated
+%    \item \texttt{space-sep-cmyk} Space-separated cyan-magenta-yellow-black
+%      values
+%    \item \texttt{space-sep-rgb} Space-separated red-green-blue values
+%      suitable for use as a PDF annotation color
+% \end{itemize}
+%
+% \begin{function}{\color_export:nnN}
+%   \begin{syntax}
+%     \cs{color_export:nnN} \Arg{color expression} \Arg{format} \Arg{tl}
+%   \end{syntax}
+%   Parses the \meta{color expression} as described earlier,
+%   then converts to the \meta{format} specified and assigns the data to the
+%   \meta{tl}.
+% \end{function}
+%
+% \begin{function}{\color_export:nnnN}
+%   \begin{syntax}
+%     \cs{color_export:nnnN} \Arg{model} \Arg{value(s)} \Arg{format} \Arg{tl}
+%   \end{syntax}
+%   Expresses the combination of \meta{model} and \meta{value(s)} in an
+%   internal representation, then converts to the \meta{format} specified and
+%   assigns the data to the \meta{tl}.
+% \end{function}
+%
+% \section{Creating new color models}
+% \label{l3color:sec:new-models}
+%
+% Additional color models are required to support specialist workflows, for
+% example those involving separations (see
+% \url{https://helpx.adobe.com/indesign/using/spot-process-colors.html}
+% for details of the use of separations in print). Color models may be split
+% into families; for the standard device-based color models (\texttt{DeviceCMYK},
+% \texttt{DeviceRGB}, \texttt{DeviceGray}), these are synonymous. This
+% is not generally the case: see the PDF reference for more details. (Note that
+% \pkg{l3color} uses the shorter names \texttt{cmyk}, etc.)
+%
+% \begin{function}{\color_model_new:nnn}
+%   \begin{syntax}
+%     \cs{color_model_new:nnn} \Arg{model} \Arg{family} \Arg{params}
+%   \end{syntax}
+%   Creates a new \meta{model} which is derived from the color model \meta{family}.
+%   The latter should be one of
+%   \begin{itemize}
+%     \item \texttt{DeviceN}
+%     \item \texttt{ICCBased}
+%     \item \texttt{Separation}
+%   \end{itemize}
+%   (The \meta{family} may be given in mixed case as-in the PDF reference:
+%   internally, case of these strings is folded.)
+%   Depending on the \meta{family}, one or more \meta{params} are mandatory or
+%   optional.
+% \end{function}
+%
+% For a \texttt{Separation} space, there are three \emph{compulsory} keys.
+% \begin{itemize}
+%   \item \texttt{name} The name of the Separation, for example the formal
+%     name of a spot color ink. Such a \meta{name} may contain spaces, etc.,
+%     which are not permitted in the \meta{model}.
+%   \item \texttt{alternative-model} An alternative device colorspace, one of
+%     \texttt{cmyk}, \texttt{rgb}, \texttt{gray} or \texttt{CIELAB}. The three
+%     parameter-based models work as described above; see below for
+%     details of CIELAB colors.
+%   \item \texttt{alternative-values} A comma-separated list of values
+%     appropriate to the \texttt{alternative-model}. This information is used by
+%     the PDF application if the \texttt{Separation} is not available.
+% \end{itemize}
+%
+% CIELAB color separations are created using the
+% \texttt{alternative-model = CIELAB} setting. These colors must also have an
+% \texttt{illuminant} key, one of \texttt{a}, \texttt{c}, \texttt{e},
+% \texttt{d50}, \texttt{d55}, \texttt{d65} or \texttt{d75}. The
+% \texttt{alternative-values} in this case are the three parameters $L*$, $a*$
+% and $b*$ of the CIELAB model. Full details of this device-independent color
+% approach are given in the documentation to the \pkg{colorspace} package.
+%
+% CIELAB colors \emph{cannot} be converted into other device-dependent color
+% spaces, and as such, mixing can only occur if colors set up using the CIELAB
+% model are also given with an alternative parameter-based model. If that is
+% not the case, \pkg{l3color} will fallback to using black as the colorant in
+% any mixing.
+%
+% For a \texttt{DeviceN} space, there is one \emph{compulsory} key.
+% \begin{itemize}
+%   \item \texttt{names} The names of the components of the \texttt{DeviceN}
+%   space. Each should be either the \meta{name} of a \texttt{Separation} model,
+%   a process color name (\texttt{cyan}, etc.) or the special name \texttt{none}.
+% \end{itemize}
+%
+% For a \texttt{ICCBased} space, there is one \emph{compulsory} key.
+% \begin{itemize}
+%   \item \texttt{file} The name of the file containing the profile.
+% \end{itemize}
+%
+% \subsection{Color profiles}
+%
+% Color profiles are used to ensure color accuracy by linking to collaboration.
+% Applying a profile can be used to standardise color which is otherwise
+% device-dependence.
+%
+% \begin{function}[added = 2021-02-23]{\color_profile_apply:nn}
+%   \begin{syntax}
+%     \cs{color_profile_apply:nn} \Arg{profile} \Arg{model}
+%   \end{syntax}
+%   This function applies a \meta{profile} to one of the device \meta{models}.
+%   The profile will then apply to all color of the selected \meta{model}. The
+%   \meta{profile} should specify an ICC profile file. The \meta{model} has to
+%   be one the standard device models: \texttt{cmyk}, \texttt{gray} or
+%   \texttt{rgb}.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3color} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=color>
+%    \end{macrocode}
+%
+% \subsection{Basics}
+%
+% \begin{variable}
+%   {\l_@@_current_tl}
+%   The color currently active for foreground (text, \emph{etc.}) material.
+%   This is stored in the form of a color model followed by one or more
+%   values. There are four pre-defined models, three of which take numerical
+%   values in the range $[0,1]$:
+%   \begin{itemize}
+%     \item \texttt{gray \meta{gray}} Grayscale color with the \meta{gray}
+%       value running from $0$ (fully black) to $1$ (fully white)
+%     \item \texttt{cmyk \meta{cyan} \meta{magenta} \meta{yellow} \meta{black}}
+%     \item \texttt{rgb \meta{red} \meta{green} \meta{blue}}
+%   \end{itemize}
+%   Notice that the value are separated by spaces. There is a fourth pre-defined
+%   model using a string value and a numerical one:
+%   \begin{itemize}
+%     \item \texttt{spot \meta{name} \meta{tint}} A pre-defined spot color,
+%       where the \meta{name} should be a pre-defined string color name and the
+%       \meta{tint} should be in the range $[0,1]$.
+%   \end{itemize}
+%
+%   Additional models may be created to allow mixing of spot colors. The
+%   number of data entries these require will depend on the number of
+%   colors to be mixed.
+%   \begin{texnote}
+%     The content of \cs{l_@@_current_tl} comprises two brace groups, the
+%     first containing the color model and the second containing the value(s)
+%     applicable in that model.
+%   \end{texnote}
+% \end{variable}
+%
+% \begin{macro}{\color_group_begin:, \color_group_end:}
+%   Grouping for color is the same as using the basic \cs{group_begin:}
+%   and \cs{group_end:} functions.  However, for semantic reasons, they
+%   are renamed here.
+%    \begin{macrocode}
+\cs_new_eq:NN \color_group_begin: \group_begin:
+\cs_new_eq:NN \color_group_end:   \group_end:
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\color_ensure_current:}
+%   A driver-independent wrapper for setting the foreground color to the
+%   current color \enquote{now}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_ensure_current:
+  { \@@_select:N \l_@@_current_tl }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\s_@@_stop}
+%   Internal scan marks.
+%    \begin{macrocode}
+\scan_new:N \s_@@_stop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_select:N, \@@_select_math:N}
+% \begin{macro}{\@@_select:nn}
+%    Take an internal color specification and pass it to the driver. This code
+%    is needed to ensure the current color but will also be used by the
+%    higher-level material.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_select:N #1
+  {
+    \exp_after:wN \@@_select:nn #1
+    \group_insert_after:N \@@_backend_reset:
+  }
+\cs_new_protected:Npn \@@_select_math:N #1
+  { \exp_after:wN \@@_select:nn #1 }
+\cs_new_protected:Npn \@@_select:nn #1#2
+  { \use:c { @@_backend_select_ #1 :n } {#2} }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_current_tl}
+%   The current color, with the model and
+%    \begin{macrocode}
+\tl_new:N \l_@@_current_tl
+\tl_set:Nn \l_@@_current_tl { { gray } { 0 } }
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Predefined color names}
+%
+% The ability to predefine colors with a name is a key part of this module and
+% means there has to be a method for storing the results. At first sight, it
+% seems natural to follow the usual \pkg{expl3} model and create a
+% \texttt{color} variable type for the process. That would then allow both
+% local and global colors, constant colors and the like. However, these names
+% need to be accessible in some form at the user level, for selection of colors
+% either simply by name or as part of a more complex expression. This does not
+% require that the full name is exposed but does require that they can be
+% looked up in a predictable way. As such, it is more useful to expose just the
+% color names as part of the interface, with the result that only local color
+% names can be created. (This is also seen for example in key creation in
+% \pkg{l3keys}.) As a result, color names are declarative (no \texttt{new}
+% functions).
+%
+% Since there is no need to manipulate colors \emph{en masse}, each is stored
+% in a two-part structure: a \texttt{prop} for the colors themselves, and a
+% \texttt{tl} for the default model for each color.
+%
+% \subsection{Setup}
+%
+% \begin{variable}{\l_@@_internal_int, \l_@@_internal_tl}
+%    \begin{macrocode}
+\int_new:N \l_@@_internal_int
+\tl_new:N \l_@@_internal_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\s_@@_mark}
+%   Internal scan marks. \cs{s_@@_stop} is already defined in \pkg{l3color-base}.
+%    \begin{macrocode}
+\scan_new:N \s_@@_mark
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_ignore_error_bool}
+%   Used to avoid issuing multiple errors if there is a change-of-model with
+%   input container an error.
+%    \begin{macrocode}
+\bool_new:N \l_@@_ignore_error_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Utility functions}
+%
+% \begin{macro}[pTF, EXP]{\color_if_exist:n}
+%   A simple wrapper to avoid needing to have the lookup repeated in too many
+%   places.To guard against a color created in a group, we need to test for
+%   entries in the |prop|.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \color_if_exist:n #1 { p , T, F, TF }
+  {
+    \prop_if_exist:cTF { l_@@_named_ #1 _prop }
+      {
+        \prop_if_empty:cTF { l_@@_named_ #1 _prop }
+          \prg_return_false:
+          \prg_return_true:
+      }
+      \prg_return_false:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_model:N, \@@_values:N}
+%   Simple abstractions.
+%    \begin{macrocode}
+\cs_new:Npn \@@_model:N #1 { \exp_after:wN \use_i:nn #1 }
+\cs_new:Npn \@@_values:N #1 { \exp_after:wN \use_ii:nn #1 }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_extract:nNN, \@@_extract:VNN}
+%   Recover the values for the standard model for a color.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_extract:nNN #1#2#3
+  {
+    \tl_set_eq:Nc #2 { l_@@_named_ #1 _tl }
+    \prop_get:cVN { l_@@_named_ #1 _prop } #2 #3
+  }
+\cs_generate_variant:Nn \@@_extract:nNN { V }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Model conversion}
+%
+% \begin{macro}{\@@_convert:nnN, \@@_convert:VVN}
+% \begin{macro}{\@@_convert:nnnN, \@@_convert:nVnN, \@@_convert:nnVN}
+% \begin{macro}[EXP]
+%   {
+%     \@@_convert_gray_gray:w
+%     \@@_convert_gray_rgb:w
+%     \@@_convert_gray_cmyk:w
+%     \@@_convert_cmyk_gray:w
+%     \@@_convert_cmyk_rgb:w
+%     \@@_convert_cmyk_cmyk:w
+%     \@@_convert_rgb_gray:w
+%     \@@_convert_rgb_rgb:w
+%     \@@_convert_rgb_cmyk:w
+%   }
+%  \begin{macro}[EXP]{\@@_convert_rgb_cmyk:nnn}
+%  \begin{macro}[EXP]{\@@_convert_rgb_cmyk:nnnn}
+%    Model conversion is carried out using standard formulae for base models,
+%    as described in the manual for \pkg{xcolor} (see also the \emph{PostScript
+%    Language Reference Manual}). For other models direct conversion might not
+%    be defined, so we go through the fallback models if necessary.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_convert:nnN #1#2#3
+  { \@@_convert:nnVN {#1} {#2} #3 #3 }
+\cs_generate_variant:Nn \@@_convert:nnN { VV }
+\cs_generate_variant:Nn \exp_last_unbraced:Nf { c }
+\cs_new_protected:Npn \@@_convert:nnnN #1#2#3#4
+  {
+    \tl_set:Ne #4
+      {
+        \cs_if_exist_use:cTF { @@_convert_ #1 _ #2 :w }
+          { #3 \s_@@_stop }
+          {
+            \cs_if_exist:cTF { @@_convert_ \use:c { c_@@_fallback_ #1 _tl } _ #2 :w }
+              {
+                \exp_last_unbraced:cf
+                  { @@_convert_ \use:c { c_@@_fallback_ #1 _tl } _ #2 :w }
+                  { \use:c { @@_convert_ #1 _ \use:c { c_@@_fallback_ #1 _tl } :w } #3 \s_@@_stop }
+                  \s_@@_stop
+              }
+              {
+                \exp_last_unbraced:cf
+                  { @@_convert_ \use:c { c_@@_fallback_ #2 _tl } _ #2 :w }
+                  {
+                    \cs_if_exist_use:cTF { @@_convert_ #1 _ \use:c { c_@@_fallback_ #2 _tl } :w }
+                      { #3 \s_@@_stop }
+                      {
+                        \exp_last_unbraced:cf
+                          { @@_convert_ \use:c { c_@@_fallback_ #1 _tl } _ \use:c { c_@@_fallback_ #2 _tl } :w }
+                          { \use:c { @@_convert_ #1 _ \use:c { c_@@_fallback_ #1 _tl } :w } #3 \s_@@_stop }
+                          \s_@@_stop
+                      }
+                  }
+                  \s_@@_stop
+              }
+          }
+      }
+  }
+\cs_generate_variant:Nn \@@_convert:nnnN { nV , nnV }
+\cs_new:Npn \@@_convert_gray_gray:w #1 \s_@@_stop
+  { #1 }
+\cs_new:Npn \@@_convert_gray_rgb:w #1 \s_@@_stop
+  { #1 ~ #1 ~ #1 }
+\cs_new:Npn \@@_convert_gray_cmyk:w #1 \s_@@_stop
+  { 0 ~ 0 ~ 0 ~ \fp_eval:n { 1 - #1 } }
+%    \end{macrocode}
+%   These rather odd values are based on \textsc{ntsc} television: the set are
+%   used for the |cmyk| conversion.
+%    \begin{macrocode}
+\cs_new:Npn \@@_convert_rgb_gray:w #1 ~ #2 ~ #3 \s_@@_stop
+  { \fp_eval:n { 0.3 * #1 + 0.59 * #2 + 0.11 * #3 } }
+\cs_new:Npn \@@_convert_rgb_rgb:w #1 \s_@@_stop
+  { #1 }
+%    \end{macrocode}
+%   The conversion from |rgb| to |cmyk| is the most complex: a two-step
+%   procedure which requires \emph{black generation} and \emph{undercolor
+%   removal} functions. The PostScript reference describes them as
+%   device-dependent, but following \pkg{xcolor} we assume they are linear.
+%   Moreover, as the likelihood of anyone using a non-unitary matrix here is
+%   tiny, we simplify and treat those two concepts as no-ops. To allow code
+%   sharing with parsing of |cmy| values, we have an intermediate function
+%   here (\cs{@@_convert_rgb_cmyk:nnn}) which actually takes |cmy| values
+%   as input.
+%    \begin{macrocode}
+\cs_new:Npn \@@_convert_rgb_cmyk:w #1 ~ #2 ~ #3 \s_@@_stop
+  {
+    \exp_args:Neee \@@_convert_rgb_cmyk:nnn
+      { \fp_eval:n { 1 - #1 } }
+      { \fp_eval:n { 1 - #2 } }
+      { \fp_eval:n { 1 - #3 } }
+  }
+\cs_new:Npn \@@_convert_rgb_cmyk:nnn #1#2#3
+  {
+    \exp_args:Ne \@@_convert_rgb_cmyk:nnnn
+      { \fp_eval:n { min( #1, #2 , #3 ) } } {#1} {#2} {#3}
+  }
+\cs_new:Npn \@@_convert_rgb_cmyk:nnnn #1#2#3#4
+  {
+    \fp_eval:n { min ( 1 , max ( 0 , #2 - #1 ) ) } \c_space_tl
+    \fp_eval:n { min ( 1 , max ( 0 , #3 - #1 ) ) } \c_space_tl
+    \fp_eval:n { min ( 1 , max ( 0 , #4 - #1 ) ) } \c_space_tl
+    #1
+  }
+\cs_new:Npn \@@_convert_cmyk_gray:w #1 ~ #2 ~ #3 ~ #4 \s_@@_stop
+  { \fp_eval:n { 1 - min ( 1 , 0.3 * #1 + 0.59 * #2 + 0.11 * #3 + #4 ) } }
+\cs_new:Npn \@@_convert_cmyk_rgb:w #1 ~ #2 ~ #3 ~ #4 \s_@@_stop
+  {
+    \fp_eval:n { 1 - min ( 1 , #1 + #4 ) } \c_space_tl
+    \fp_eval:n { 1 - min ( 1 , #2 + #4 ) } \c_space_tl
+    \fp_eval:n { 1 - min ( 1 , #3 + #4 ) }
+  }
+\cs_new:Npn \@@_convert_cmyk_cmyk:w #1 \s_@@_stop
+  { #1 }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Color expressions}
+%
+% \begin{variable}
+%   {\l_@@_model_tl, \l_@@_value_tl, \l_@@_next_model_tl, \l_@@_next_value_tl}
+%   Working space to store the color data whilst doing calculations: keeping
+%   it on the stack is attractive but gets tricky (return is non-trivial).
+%    \begin{macrocode}
+\tl_new:N \l_@@_model_tl
+\tl_new:N \l_@@_value_tl
+\tl_new:N \l_@@_next_model_tl
+\tl_new:N \l_@@_next_value_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_parse:nN}
+% \begin{macro}{\@@_parse_aux:nN}
+% \begin{macro}{\@@_parse_eq:Nn}
+% \begin{macro}{\@@_parse_eq:nNn}
+% \begin{macro}{\@@_parse:Nw}
+% \begin{macro}{\@@_parse_loop_init:Nnn}
+% \begin{macro}{\@@_parse_loop:w}
+% \begin{macro}{\@@_parse_loop_check:nn}
+% \begin{macro}{\@@_parse_loop:nn}
+% \begin{macro}{\@@_parse_gray:n, \@@_parse_std:n}
+% \begin{macro}{\@@_parse_break:w}
+% \begin{macro}{\@@_parse_end:}
+% \begin{macro}[EXP]{\@@_parse_mix:Nnnn, \@@_parse_mix:NVVn}
+% \begin{macro}[EXP]{\@@_parse_mix:nNnn}
+% \begin{macro}[EXP]
+%   {
+%     \@@_parse_mix_gray:nw ,
+%     \@@_parse_mix_rgb:nw  ,
+%     \@@_parse_mix_cmyk:nw
+%   }
+%   The main function for parsing color expressions removes actives but
+%   otherwise expands, then starts working through the expression itself.
+%   At the end, we apply the payload.
+%    \begin{macrocode}
+\cs_new_protected:Npe \@@_parse:nN #1#2
+  {
+    \tl_set:Ne \exp_not:c { l_@@_named_ . _tl }
+      { \exp_not:N \@@_model:N \exp_not:N \l_@@_current_tl }
+    \prop_put:NVe \exp_not:c { l_@@_named_ . _prop }
+      \exp_not:c { l_@@_named_ . _tl }
+      { \exp_not:N \@@_values:N \exp_not:N \l_@@_current_tl }
+    \exp_not:N \exp_args:Ne \exp_not:N \@@_parse_aux:nN
+      { \exp_not:N \tl_to_str:n {#1} } #2
+  }
+%    \end{macrocode}
+%   Before going to all of the effort of parsing an expression, these two
+%   precursor functions look for a pre-defined name, either on its own or
+%   with a trailing |!| (which is the same thing).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_aux:nN #1#2
+  {
+    \color_if_exist:nTF {#1}
+      { \@@_parse_set_eq:Nn #2 {#1} }
+      { \@@_parse:Nw #2#1 ! \s_@@_stop }
+    \@@_check_model:N #2
+  }
+\cs_new_protected:Npn \@@_parse_set_eq:Nn #1#2
+  {
+    \tl_if_empty:NTF \l_color_fixed_model_tl
+      { \exp_args:Nv \@@_parse_set_eq:nNn { l_@@_named_ #2 _tl } }
+      { \exp_args:NV \@@_parse_set_eq:nNn \l_color_fixed_model_tl }
+        #1 {#2}
+  }
+%    \end{macrocode}
+%    Here, we have to allow for the case where there is a fixed model:
+%    that can't be swept up by generic conversion as we are dealing with a
+%    named color.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_set_eq:nNn #1#2#3
+  {
+    \prop_get:cnNTF
+      { l_@@_named_ #3 _prop } {#1}
+      \l_@@_value_tl
+      { \tl_set:Ne #2 { {#1} { \l_@@_value_tl } } }
+      {
+        \tl_set_eq:Nc \l_@@_model_tl { l_@@_named_ #3 _tl }
+        \prop_get:cVN { l_@@_named_ #3 _prop } \l_@@_model_tl
+          \l_@@_value_tl
+        \@@_convert:nnN
+          \l_@@_model_tl {#1} \l_@@_value_tl
+        \tl_set:Ne #2
+          {
+            {#1}
+            { \l_@@_value_tl }
+          }
+      }
+  }
+\cs_new_protected:Npn \@@_parse:Nw #1#2 ! #3 \s_@@_stop
+  {
+    \color_if_exist:nTF {#2}
+      {
+        \tl_if_blank:nTF {#3}
+          { \@@_parse_set_eq:Nn #1 {#2} }
+          { \@@_parse_loop_init:Nnn #1 {#2} {#3} }
+      }
+      {
+        \msg_error:nnn { color } { unknown-color } {#2}
+        \tl_set:Nn \l_@@_current_tl { { gray } { 0 } }
+      }
+  }
+%    \end{macrocode}
+%   Once we establish that a full parse is needed, the next job is to get the
+%   detail of the first color. That will determine the model we use for the
+%   calculation: splitting here makes checking that a bit easier.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_loop_init:Nnn #1#2#3
+  {
+    \group_begin:
+      \@@_extract:nNN {#2} \l_@@_model_tl \l_@@_value_tl
+      \@@_parse_loop:w #3 ! ! ! ! \s_@@_stop
+      \tl_set:Ne \l_@@_internal_tl
+        { { \l_@@_model_tl } { \l_@@_value_tl } }
+    \exp_args:NNNV \group_end:
+    \tl_set:Nn #1 \l_@@_internal_tl
+  }
+%    \end{macrocode}
+%   This is the loop proper: there can be an open-ended set of colors to parse,
+%   separated by |!| tokens. There are a few cases to look out for. At the end
+%   of the expression and with we find a mix of $100$ then we simply skip the
+%   next color entirely (we can't stop the loop as there might be a further
+%   valid color to mix in). On the other hand, if we get a mix of $0$ then
+%   drop everything so far and start again. There is also a trailing
+%   |white| to \enquote{read in} if the final explicit data is a mix.
+%   Those conditions are separate from actually looping, which is therefore
+%   sorted out by checking if we have further data to process: in contrast
+%   to \pkg{xcolor}, we don't allow |!!| so the test can be simplified.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_loop:w #1 ! #2 ! #3 ! #4 ! #5 \s_@@_stop
+  {
+    \tl_if_blank:nF {#1}
+      {
+        \bool_lazy_and:nnTF
+          { \fp_compare_p:nNn {#1} > { 0 } }
+          { \fp_compare_p:nNn {#1} < { 100 } }
+          {
+            \use:e
+              {
+                \@@_parse_loop:nn {#1}
+                  { \tl_if_blank:nTF {#2} { white } {#2} }
+              }
+          }
+          { \@@_parse_loop_check:nn {#1} {#2} }
+      }
+    \tl_if_blank:nF {#3}
+      { \@@_parse_loop:w #3 ! #4 ! #5 \s_@@_stop }
+    \@@_parse_end:
+  }
+%    \end{macrocode}
+%   As these are unusual cases, we accept slower performance here for clearer
+%   code: check for the error conditions, handle the boundary cases after
+%   that.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_loop_check:nn #1#2
+  {
+    \bool_if:NF \l_@@_ignore_error_bool
+      {
+        \bool_lazy_or:nnT
+          { \fp_compare_p:nNn {#1} < { 0 } }
+          { \fp_compare_p:nNn {#1} > { 100 } }
+          { \msg_error:nnnnn { color } { out-of-range } {#1} { 0 } { 100 } }
+      }
+    \fp_compare:nNnF {#1} > \c_zero_fp
+      {
+        \tl_if_blank:nTF {#2}
+          { \@@_extract:nNN { white } }
+          { \@@_extract:nNN {#2} }
+            \l_@@_model_tl \l_@@_value_tl
+      }
+  }
+%    \end{macrocode}
+%   The \enquote{payload} of calculation in the loop first. If the model for
+%   the upcoming color is different from that of the existing (partial) color,
+%   convert the model. For |gray| the two are flipped round so that the outcome
+%   is something with \enquote{real} color. We are then in a position to do the
+%   actual calculation itself. The two auxiliaries here give us a way to break
+%   the loop should an invalid name be found.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_loop:nn #1#2
+  {
+    \color_if_exist:nTF {#2}
+      {
+        \@@_extract:nNN {#2} \l_@@_next_model_tl \l_@@_next_value_tl
+        \tl_if_eq:NNF \l_@@_model_tl \l_@@_next_model_tl
+          {
+            \str_if_eq:VnTF \l_@@_model_tl { gray }
+              { \@@_parse_gray:n {#2} }
+              { \@@_parse_std:n {#2} }
+          }
+        \tl_set:Ne \l_@@_value_tl
+          {
+            \@@_parse_mix:NVVn
+              \l_@@_model_tl \l_@@_value_tl \l_@@_next_value_tl {#1}
+          }
+      }
+      {
+        \msg_error:nnn { color } { unknown-color } {#2}
+        \@@_extract:nNN { black } \l_@@_model_tl \l_@@_value_tl
+        \@@_parse_break:w
+      }
+  }
+%    \end{macrocode}
+%   The \texttt{gray} model needs special handling: the models need to be
+%   swapped: we do that using a dedicated function.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_parse_gray:n #1
+  {
+    \tl_set_eq:NN \l_@@_model_tl \l_@@_next_model_tl
+    \tl_set:Nn \l_@@_next_model_tl { gray }
+    \exp_args:NnV \@@_convert:nnN { gray } \l_@@_model_tl
+      \l_@@_value_tl
+    \prop_get:cVN { l_@@_named_ #1 _prop } \l_@@_model_tl
+      \l_@@_next_value_tl
+  }
+\cs_new_protected:Npn \@@_parse_std:n #1
+  {
+    \prop_get:cVNF { l_@@_named_ #1 _prop }
+      \l_@@_model_tl
+      \l_@@_next_value_tl
+        {
+          \@@_convert:VVN
+            \l_@@_next_model_tl
+            \l_@@_model_tl
+            \l_@@_next_value_tl
+        }
+  }
+\cs_new_protected:Npn \@@_parse_break:w #1 \@@_parse_end: { }
+\cs_new_protected:Npn \@@_parse_end: { }
+%    \end{macrocode}
+%   Do the vector arithmetic: mainly a question of shuffling input, along
+%   with one pre-calculation to keep down the use of division.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_mix:Nnnn #1#2#3#4
+  {
+    \exp_args:Nf \@@_parse_mix:nNnn
+      { \fp_eval:n { #4 / 100 } }
+      #1 {#2} {#3}
+  }
+\cs_generate_variant:Nn \@@_parse_mix:Nnnn { NVV }
+\cs_new:Npn \@@_parse_mix:nNnn #1#2#3#4
+  {
+    \use:c { @@_parse_mix_ #2 :nw } {#1}
+      #3 \s_@@_mark #4 \s_@@_stop
+  }
+\cs_new:Npn \@@_parse_mix_gray:nw #1#2 \s_@@_mark #3 \s_@@_stop
+  { \fp_eval:n { #2 * #1 + #3 * ( 1 - #1 ) } }
+\cs_new:Npn \@@_parse_mix_rgb:nw
+  #1#2 ~ #3 ~ #4 \s_@@_mark #5 ~ #6 ~ #7 \s_@@_stop
+  {
+    \fp_eval:n { #2 * #1 + #5 * ( 1 - #1 ) } \c_space_tl
+    \fp_eval:n { #3 * #1 + #6 * ( 1 - #1 ) } \c_space_tl
+    \fp_eval:n { #4 * #1 + #7 * ( 1 - #1 ) }
+  }
+\cs_new:Npn \@@_parse_mix_cmyk:nw
+  #1#2 ~ #3 ~ #4 ~ #5 \s_@@_mark #6 ~ #7 ~ #8 ~ #9 \s_@@_stop
+  {
+    \fp_eval:n { #2 * #1 + #6 * ( 1 - #1 ) } \c_space_tl
+    \fp_eval:n { #3 * #1 + #7 * ( 1 - #1 ) } \c_space_tl
+    \fp_eval:n { #4 * #1 + #8 * ( 1 - #1 ) } \c_space_tl
+    \fp_eval:n { #5 * #1 + #9 * ( 1 - #1 ) }
+  }
+%    \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}
+%
+% \begin{macro}[EXP]
+%   {
+%     \@@_parse_model_gray:w, \@@_parse_model_rgb:w,
+%     \@@_parse_model_cmyk:w
+%   }
+% \begin{macro}[EXP]{\@@_parse_number:n}
+% \begin{macro}[EXP]{\@@_parse_number:w}
+%   Turn the input into internal form, also tidying up the number quickly.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_model_gray:w #1 , #2 \s_@@_stop
+  { { gray } { \@@_parse_number:n {#1} } }
+\cs_new:Npn \@@_parse_model_rgb:w #1 , #2 , #3 , #4 \s_@@_stop
+  {
+    { rgb }
+    {
+      \@@_parse_number:n {#1} ~
+      \@@_parse_number:n {#2} ~
+      \@@_parse_number:n {#3}
+    }
+  }
+\cs_new:Npn \@@_parse_model_cmyk:w #1 , #2 , #3 , #4 , #5 \s_@@_stop
+  {
+    { cmyk }
+    {
+      \@@_parse_number:n {#1} ~
+      \@@_parse_number:n {#2} ~
+      \@@_parse_number:n {#3} ~
+      \@@_parse_number:n {#4}
+    }
+  }
+\cs_new:Npn \@@_parse_number:n #1
+  {  \@@_parse_number:w #1 . 0 . \s_@@_stop }
+\cs_new:Npn \@@_parse_number:w #1 . #2 . #3 \s_@@_stop
+  { \tl_if_blank:nTF {#1} { 0 } {#1} . #2 }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {
+%     \@@_parse_model_Gray:w, \@@_parse_model_hsb:w,
+%     \@@_parse_model_Hsb:w, \@@_parse_model_HSB:w,
+%     \@@_parse_model_HTML:w, \@@_parse_model_RGB:w
+%   }
+% \begin{macro}[EXP]{\@@_parse_model_hsb:nnn, \@@_parse_model_hsb_aux:nnn}
+% \begin{macro}[EXP]{\@@_parse_model_hsb:nnnn}
+% \begin{macro}[EXP]{\@@_parse_model_hsb:nnnnn}
+% \begin{macro}[EXP]
+%   {
+%     \@@_parse_model_hsb_0:nnnn ,
+%     \@@_parse_model_hsb_1:nnnn ,
+%     \@@_parse_model_hsb_2:nnnn ,
+%     \@@_parse_model_hsb_3:nnnn ,
+%     \@@_parse_model_hsb_4:nnnn ,
+%     \@@_parse_model_hsb_5:nnnn
+%   }
+% \begin{macro}[EXP]{\@@_parse_model_wave:w}
+% \begin{macro}[EXP]
+%   {\@@_parse_model_wave_auxi:nn, \@@_parse_model_wave_auxii:nn}
+% \begin{macro}[EXP]{\@@_parse_model_wave_rho:n}
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_model_Gray:w #1 , #2 \s_@@_stop
+  { { gray } { \fp_eval:n { #1 / 15 } } }
+\cs_new:Npn \@@_parse_model_hsb:w #1 , #2 , #3 , #4 \s_@@_stop
+  { \@@_parse_model_hsb:nnn {#1} {#2} {#3} }
+\cs_new:Npn \@@_parse_model_Hsb:w #1 , #2 , #3 , #4 \s_@@_stop
+  {
+    \exp_args:Ne \@@_parse_model_hsb:nnn { \fp_eval:n { #1 / 360 } }
+      {#2} {#3}
+  }
+%    \end{macrocode}
+%   The conversion here is non-trivial but is described at length
+%   in the \pkg{xcolor} manual. For ease, we calculate the integer
+%   and fractional parts of the hue first, then use them to work out the
+%   possible values for $r$, $g$ and $b$ before putting them in the correct
+%   places.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_model_hsb:nnn #1#2#3
+  {
+    { rgb }
+    {
+      \exp_args:Ne \@@_parse_model_hsb_aux:nnn
+        { \fp_eval:n { 6 * (#1) } } {#2} {#3}
+    }
+  }
+\cs_new:Npn \@@_parse_model_hsb_aux:nnn #1#2#3
+  {
+    \exp_args:Nee \@@_parse_model_hsb_aux:nnnn
+      { \fp_eval:n { floor(#1) } } { \fp_eval:n { #1 - floor(#1) } }
+      {#2} {#3}
+  }
+\cs_new:Npn \@@_parse_model_hsb_aux:nnnn #1#2#3#4
+  {
+    \use:e
+      {
+        \exp_not:N \@@_parse_model_hsb_aux:nnnnn
+          { \@@_parse_number:n {#4} }
+          { \fp_eval:n { round(#4 * (1 - #3) ,5) } }
+          { \fp_eval:n { round(#4 * ( 1 - #3 * #2 ) ,5) } }
+          { \fp_eval:n { round(#4 * ( 1 - #3 * (1 - #2) ) ,5) } }
+          {#1}
+      }
+  }
+\cs_new:Npn \@@_parse_model_hsb_aux:nnnnn #1#2#3#4#5
+  { \use:c { @@_parse_model_hsb_ #5 :nnnn } {#1} {#2} {#3} {#4} }
+\cs_new:cpn { @@_parse_model_hsb_0:nnnn } #1#2#3#4 { #1 ~ #4 ~ #2 }
+\cs_new:cpn { @@_parse_model_hsb_1:nnnn } #1#2#3#4 { #3 ~ #1 ~ #2 }
+\cs_new:cpn { @@_parse_model_hsb_2:nnnn } #1#2#3#4 { #2 ~ #1 ~ #4 }
+\cs_new:cpn { @@_parse_model_hsb_3:nnnn } #1#2#3#4 { #2 ~ #3 ~ #1 }
+\cs_new:cpn { @@_parse_model_hsb_4:nnnn } #1#2#3#4 { #4 ~ #2 ~ #1 }
+\cs_new:cpn { @@_parse_model_hsb_5:nnnn } #1#2#3#4 { #1 ~ #2 ~ #3 }
+\cs_new:cpn { @@_parse_model_hsb_6:nnnn } #1#2#3#4 { #1 ~ #2 ~ #2 }
+\cs_new:Npn \@@_parse_model_HSB:w #1 , #2 , #3 , #4 \s_@@_stop
+  {
+    \exp_args:Neee \@@_parse_model_hsb:nnn
+      { \fp_eval:n { round((#1) / 240,5) } }
+      { \fp_eval:n { round((#2) / 240,5) } }
+      { \fp_eval:n { round((#3) / 240,5) } }
+  }
+\cs_new:Npn \@@_parse_model_HTML:w #1 , #2 \s_@@_stop
+  { \@@_parse_model_HTML_aux:w #1 0 0 0 0 0 0 \s_@@_stop }
+\cs_new:Npn \@@_parse_model_HTML_aux:w #1#2#3#4#5#6#7 \s_@@_stop
+  {
+    { rgb }
+    {
+      \fp_eval:n { round(\int_from_hex:n {#1#2} / 255,5) } ~
+      \fp_eval:n { round(\int_from_hex:n {#3#4} / 255,5) } ~
+      \fp_eval:n { round(\int_from_hex:n {#5#6} / 255,5) }
+    }
+  }
+\cs_new:Npn \@@_parse_model_RGB:w #1 , #2 , #3 , #4 \s_@@_stop
+  {
+    { rgb }
+    {
+      \fp_eval:n { round((#1) / 255,5) } ~
+      \fp_eval:n { round((#2) / 255,5) } ~
+      \fp_eval:n { round((#3) / 255,5) }
+    }
+  }
+%    \end{macrocode}
+%  Following the description in the \pkg{xcolor} manual. As we always use |rgb|,
+%  there is no need to find the sixth, we just pas the information straight
+%  to the |hsb| auxiliary defined earlier.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_model_wave:w #1 , #2 \s_@@_stop
+  {
+    { rgb }
+    {
+      \fp_compare:nNnTF {#1} < { 420 }
+        { \@@_parse_model_wave_auxi:nn {#1} { 0.3 + 0.7 * (#1 - 380) / 40 }
+        }
+        {
+          \fp_compare:nNnTF {#1} > { 700 }
+            { \@@_parse_model_wave_auxi:nn {#1} { 0.3 + 0.7 * (#1 - 780) / -80 } }
+            { \@@_parse_model_wave_auxi:nn {#1} { 1 } }
+        }
+    }
+  }
+\cs_new:Npn \@@_parse_model_wave_auxi:nn #1#2
+  {
+    \fp_compare:nNnTF {#1} < { 440 }
+      {
+        \@@_parse_model_wave_auxii:nn
+          { 4 + \@@_parse_model_wave_rho:n { (#1 - 440) / -60 } }
+          {#2}
+      }
+      {
+        \fp_compare:nNnTF {#1} < { 490 }
+          {
+            \@@_parse_model_wave_auxii:nn
+              { 4 - \@@_parse_model_wave_rho:n { (#1 - 440) / 50 } }
+              {#2}
+          }
+          {
+            \fp_compare:nNnTF {#1} < { 510 }
+              {
+                \@@_parse_model_wave_auxii:nn
+                  { 2 + \@@_parse_model_wave_rho:n { (#1 - 510) / -20 } }
+                  {#2}
+              }
+              {
+                \fp_compare:nNnTF {#1} < { 580 }
+                  {
+                    \@@_parse_model_wave_auxii:nn
+                      { 2 - \@@_parse_model_wave_rho:n { (#1 - 510) / 70 } }
+                      {#2}
+                  }
+                  {
+                    \fp_compare:nNnTF {#1} < { 645 }
+                      {
+                        \@@_parse_model_wave_auxii:nn
+                          { \@@_parse_model_wave_rho:n { (#1 - 645) / -65 } }
+                          {#2}
+                      }
+                      { \@@_parse_model_wave_auxii:nn { 0 } {#2} }
+                  }
+              }
+          }
+      }
+  }
+\cs_new:Npn \@@_parse_model_wave_auxii:nn #1#2
+  {
+    \exp_args:Neee \@@_parse_model_hsb_aux:nnn
+      { \fp_eval:n {#1} }
+      { 1 }
+      { \@@_parse_model_wave_rho:n {#2} }
+  }
+\cs_new:Npn \@@_parse_model_wave_rho:n #1
+  { \fp_eval:n { min(1, max(0,#1) ) } }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_model_cmy:w}
+%   Simply pass data to the conversion functions.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_model_cmy:w #1 , #2 , #3 , #4 \s_@@_stop
+  {
+    { cmyk }
+    { \@@_convert_rgb_cmyk:nnn {#1} {#2} {#3} }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_model_tHsb:w}
+% \begin{macro}{\@@_parse_model_tHsb:n}
+% \begin{macro}{\@@_parse_model_tHsb:nw}
+%   There are three stages to the process here: bring the |tH| argument into
+%   the normal range, divide through to get to |hsb| and finally convert that
+%   to |rgb|. The final stage can be delegated to the parsing function for
+%   |hsb|, and the conversion from |Hsb| to |hsb| is trivial, so the main focus
+%   here is the first stage. We use a simple expandable loop to do the work,
+%   and we implement the equation given in the \pkg{xcolor} manual
+%   (number~85 there) as a simple expression.
+%    \begin{macrocode}
+\cs_new:Npn \@@_parse_model_tHsb:w #1 , #2 , #3 , #4 \s_@@_stop
+  {
+    \exp_args:Ne \@@_parse_model_hsb:nnn
+      { \@@_parse_model_tHsb:n {#1} } {#2} {#3}
+  }
+\cs_new:Npn \@@_parse_model_tHsb:n #1
+  {
+    \@@_parse_model_tHsb:nw {#1}
+        0 ,   0 ; 
+       60 ,  30 ;
+      120 ,  60 ;
+      180 , 120 ;
+      210 , 180 ;
+      240 , 240 ;
+      360 , 360 ;
+      \q_recursion_tail , ;
+      \q_recursion_stop
+  }
+\cs_new:Npn \@@_parse_model_tHsb:nw #1 #2 , #3 ; #4 , #5 ;
+  {
+    \quark_if_recursion_tail_stop_do:nn {#4} { 0 }
+    \fp_compare:nNnTF {#1} > {#4}
+      { \@@_parse_model_tHsb:nw {#1} #4 , #5 ; }
+      {
+        \use_i_delimit_by_q_recursion_stop:nw
+          { \fp_eval:n { ((#1 - #2) / (#4 - #2) * (#5 - #3) + #3) / 360 } }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_parse_model_&spot:w}
+%   We cannot extract data here from that passed by \pkg{xcolor}, so
+%   we fall back on a black tint. 
+%    \begin{macrocode}
+\cs_new:cpn { @@_parse_model_&spot:w } #1 , #2 \s_@@_stop
+  { { gray } { #1 } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Selecting colors (and color models)}
+%
+% \begin{variable}{\l_color_fixed_model_tl}
+%   For selecting a single fixed model.
+%    \begin{macrocode}
+\tl_new:N \l_color_fixed_model_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_check_model:N}
+% \begin{macro}{\@@_check_model:nn}
+%   Check that the model in use is the one required.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_check_model:N #1
+  {
+    \tl_if_empty:NF \l_color_fixed_model_tl
+      {
+        \exp_after:wN \@@_check_model:nn #1
+        \tl_if_eq:NNF \l_@@_model_tl \l_color_fixed_model_tl
+          {
+            \@@_convert:VVN \l_@@_model_tl \l_color_fixed_model_tl
+              \l_@@_value_tl
+          }
+        \tl_set:Ne #1
+          { { \l_color_fixed_model_tl } { \l_@@_value_tl } }
+      }
+  }
+\cs_new_protected:Npn \@@_check_model:nn #1#2
+  {
+    \tl_set:Nn \l_@@_model_tl {#1}
+    \tl_set:Nn \l_@@_value_tl {#2}
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_finalise_current:}
+%   A backend-neutral location for \enquote{last minute} manipulations before
+%   handing off to the backend code.  We set the special |.| syntax here: this
+%   will therefore always be available. The finalisation is separate from the
+%   main function so it can also be applied to \emph{e.g.}~page color.
+%    \begin{macrocode}
+\cs_new_protected:Npe \@@_finalise_current:
+  {
+    \tl_set:Ne \exp_not:c { l_@@_named_ . _tl }
+      { \exp_not:N \@@_model:N \exp_not:N \l_@@_current_tl }
+    \prop_clear:N \exp_not:c { l_@@_named_ . _prop }
+    \prop_put:NVe \exp_not:c { l_@@_named_ . _prop }
+      \exp_not:c { l_@@_named_ . _tl }
+      { \exp_not:N \@@_values:N \exp_not:N \l_@@_current_tl }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\color_select:n}
+% \begin{macro}{\color_select:nn}
+% \begin{macro}{\@@_select_main:Nw, \@@_select_loop:Nw}
+% \begin{macro}{\@@_select:nnN}
+% \begin{macro}{\@@_select_swap:Nnn}
+%   Parse the input expressions then get the backend to actually activate
+%   them. The main complexity here is the need to check through multiple models.
+%   That is done \enquote{locally} here as the approach is subtly different to
+%   when different models are being stored.
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_select:n #1
+  {
+    \@@_parse:nN {#1} \l_@@_current_tl
+    \@@_finalise_current:
+    \@@_select:N \l_@@_current_tl
+  }
+\cs_new_protected:Npn \color_select:nn #1#2
+  {
+    \@@_select_main:Nw \l_@@_current_tl
+      #1 / / \s_@@_mark #2 / / \s_@@_stop
+    \@@_finalise_current:
+    \@@_select:N \l_@@_current_tl
+  }
+%    \end{macrocode}
+%   If the first color model is the fixed one, or if there is no fixed
+%   model, we don't need most of the data: just set up and apply the backend
+%   function.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_select_main:Nw
+  #1 #2 / #3 / #4 \s_@@_mark #5 / #6 / #7 \s_@@_stop
+  {
+    \@@_select:nnN {#2} {#5} #1
+    \bool_lazy_or:nnF
+      { \tl_if_empty_p:N \l_color_fixed_model_tl }
+      { \str_if_eq_p:nV {#2} \l_color_fixed_model_tl }
+      { \@@_select_loop:Nw #1 #3 / #4 \s_@@_mark #6 / #7 \s_@@_stop }
+  }
+%    \end{macrocode}
+%   If a fixed model applies, we need to check each possible value in order.
+%   If there is no hit at all, fall back on the generic formula-based
+%   interchange.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_select_loop:Nw
+  #1 #2 / #3 \s_@@_mark #4 / #5 \s_@@_stop
+  {
+    \str_if_eq:nVTF {#2} \l_color_fixed_model_tl
+      { \@@_select:nnN {#2} {#4} #1 }
+      {
+        \tl_if_blank:nTF {#2}
+          { \exp_after:wN \@@_select_swap:Nnn \exp_after:wN #1 #1 }
+          { \@@_select_loop:Nw #1 #3 \s_@@_mark #5 \s_@@_stop }
+      }
+  }
+\cs_new_protected:Npn \@@_select:nnN #1#2#3
+  {
+    \cs_if_exist:cTF { @@_parse_model_ #1 :w }
+      {
+        \tl_set:Ne #3
+          { \use:c { @@_parse_model_ #1 :w } #2 , 0 , 0 , 0 , 0 \s_@@_stop }
+      }
+      { \msg_error:nnn { color } { unknown-model } {#1} }
+  }
+\cs_new_protected:Npn \@@_select_swap:Nnn #1#2#3
+  {
+    \@@_convert:nVnN {#2} \l_color_fixed_model_tl {#3} \l_@@_value_tl
+    \tl_set:Ne #1
+      { { \l_color_fixed_model_tl } { \l_@@_value_tl } }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Math color}
+%
+% The approach here is the same as for the \LaTeXe{} \cs{mathcolor} command,
+% but as we are working at the \pkg{expl3} level we can make some minor
+% changes.
+%
+% \begin{macro}{\l_color_math_active_tl}
+%   Tokens representing active sub/superscripts.
+%    \begin{macrocode}
+\tl_new:N \l_color_math_active_tl
+\tl_set:Nn \l_color_math_active_tl { ' }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_math_seq}
+%   Not all engines have multiple color stacks, and at the same time we are
+%   not expecting breaking within a colored math fragment. So we track the
+%   color stack ourselves.
+%    \begin{macrocode}
+\seq_new:N \g_@@_math_seq
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\color_math:nn}
+% \begin{macro}{\color_math:nnn}
+% \begin{macro}{\@@_math:nn}
+%   The basic set up here is relatively simple: store the current color,
+%   parse the new color as-normal, then switch color before inserting the
+%   tokens we are asked to change. The tricky part is right at the end,
+%   handling the reset.
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_math:nn #1#2
+  {
+    \@@_math:nn {#2}
+      { \@@_parse:nN {#1} \l_@@_current_tl }
+  }
+\cs_new_protected:Npn \color_math:nnn #1#2#3
+  {
+    \@@_math:nn {#3}
+      {
+        \@@_select_main:Nw \l_@@_current_tl
+          #1 / / \s_@@_mark #2 / / \s_@@_stop
+      }
+  }
+\cs_new_protected:Npn \@@_math:nn #1#2
+  {
+    \seq_gpush:NV \g_@@_math_seq \l_@@_current_tl
+    #2
+    \@@_select_math:N \l_@@_current_tl
+    #1
+    \@@_math_scan:w
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \@@_math_scan:w      ,
+%     \@@_math_scan_auxi:  ,
+%     \@@_math_scan_auxii: ,
+%     \@@_math_scan_end:
+%   }
+%   The complication when changing the color back is due to the fact
+%   that the \cs{color_math:nn(n)} may be followed by \verb=^= or \verb=_=
+%   or the hidden superscript (for example \texttt{'}) and its argument may
+%   end in a \tn{mathop} in which case the sub- and superscripts may be
+%   attached as \cs{limits} instead of after the material. All cases
+%   need separate treatment. To avoid repeatedly collecting the same
+%   token, we first check for an alignment tab: assuming we don't have
+%   one of those, we can \enquote{recycle} \cs{l_peek_token} safely.
+%   As we have an explicit \cs{c_alignment_token}, there needs to be
+%   an align-safe group present.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_math_scan:w
+  {
+    \peek_remove_filler:n
+      {
+        \group_align_safe_begin:
+        \peek_catcode:NTF \c_alignment_token
+          {
+            \group_align_safe_end:
+            \@@_math_scan_end:
+          }
+          {
+            \group_align_safe_end:
+            \@@_math_scan_auxi:
+          }
+      }
+  }
+%    \end{macrocode}
+%   Dealing with literal |_| and |^| is easy, and as we have exactly two cases,
+%   we can hard-code this. We use a hard-coded list for limits: these are all
+%   primitives. The \cs{use_none:n} here also removes the test token so it is
+%   left just in the right place.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_math_scan_auxi:
+  {
+    \token_case_catcode:NnTF \l_peek_token
+      {
+        \c_math_subscript_token   { }
+        \c_math_superscript_token { }
+      }
+      { \@@_math_scripts:Nw }
+      {
+        \token_case_meaning:NnTF \l_peek_token
+          {
+            \tex_limits:D        { \tex_limits:D }
+            \tex_nolimits:D      { \tex_nolimits:D }
+            \tex_displaylimits:D { \tex_displaylimits:D }
+          }
+          { \@@_math_scan:w \use_none:n }
+          { \@@_math_scan_auxii: }
+      }
+  }
+%    \end{macrocode}
+%   The one final case to handle is math-active tokens, most obviously
+%   \texttt{'}, as these won't be covered earlier.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_math_scan_auxii:
+  {
+    \tl_map_inline:Nn \l_color_math_active_tl
+      {
+        \token_if_eq_meaning:NNT \l_peek_token ##1
+          {
+            \tl_map_break:n
+              {
+                \use_i:nn
+                  { \@@_math_scan_auxiii:N ##1 }
+              }
+          }
+        \@@_math_scan_end:
+      }
+  }
+\cs_new_protected:Npn \@@_math_scan_auxiii:N #1
+  {
+    \exp_after:wN \exp_after:wN \exp_after:wN \@@_math_scan:w
+      \char_generate:nn { `#1 } { 13 }
+  }
+\cs_new_protected:Npn \@@_math_scan_end:
+  {
+    \@@_backend_reset:
+    \seq_gpop:NN \g_@@_math_seq \l_@@_current_tl
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_math_scripts:Nw}
+% \begin{macro}{\@@_math_script_aux:N}
+%   The tricky part of handling sub and superscripts is that we have
+%   to reset color to the one that is on the stack but reset it back
+%   to what it was before to allow for cases like
+% \begin{verbatim}
+%   \[  \color_math:n { red } { a + \sum } _ { i = 1 } ^ { n }  \]
+% \end{verbatim}
+%   Here, \TeX{} constructs a \cs{vbox} stacking subscript, summation
+%   sign, and superscript. So technically the superscript comes first
+%   and the \cs{sum} that should get colored red is the middle.
+%
+%  The approach here is to set up a brace group immediately after the 
+%  script token, then to set the color appropriately in that argument.
+%  We need an extra group to keep the color contained, and as we
+%  need to allow for an explicit closing brace in the source, the
+%  inner group also is a brace one rather than \cs{group_begin:}-based.
+%  At the end of the outer group we need to insert \cs{@@_math_scan:w}
+%  to continue the search for a second script token.
+%
+%  Notice that here we \emph{don't} need to use the math-specific
+%  color selector as we can allow the
+%  |\group_insert_after:N \@@_backend_reset:| to operate normally.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_math_scripts:Nw #1
+  {
+    #1
+    \c_group_begin_token
+      \c_group_begin_token
+        \seq_get:NN \g_@@_math_seq \l_@@_current_tl
+        \@@_select:N \l_@@_current_tl
+        \group_insert_after:N \c_group_end_token
+        \group_insert_after:N \@@_math_scan:w
+    \peek_remove_filler:n
+      {
+        \peek_catcode_remove:NF \c_group_begin_token
+          { \@@_math_script_aux:N }
+      }
+  }
+%    \end{macrocode}
+%   Deal with the case where we do not have an explicit brace pair in the
+%   source.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_math_script_aux:N #1 { #1 \c_group_end_token }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Fill and stroke color}
+%
+% \begin{macro}{\color_fill:n, \color_stroke:n}
+% \begin{macro}{\color_fill:nn, \color_stroke:nn}
+% \begin{macro}{\@@_draw:nnn}
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_fill:n #1
+  {
+    \@@_parse:nN {#1} \l_@@_current_tl
+    \exp_after:wN \@@_draw:nnn \l_@@_current_tl { fill }
+  }
+\cs_new_protected:Npn \color_stroke:n #1
+  {
+    \@@_parse:nN {#1} \l_@@_current_tl
+    \exp_after:wN \@@_draw:nnn \l_@@_current_tl { stroke }
+  }
+\cs_new_protected:Npn \color_fill:nn #1#2
+  {
+    \@@_select_main:Nw \l_@@_current_tl
+      #1 / / \s_@@_mark #2 / / \s_@@_stop
+    \exp_after:wN \@@_draw:nnn \l_@@_current_tl { fill }
+  }
+\cs_new_protected:Npn \color_stroke:nn #1#2
+  {
+    \@@_select_main:Nw \l_@@_current_tl
+      #1 / / \s_@@_mark #2 / / \s_@@_stop
+    \exp_after:wN \@@_draw:nnn \l_@@_current_tl { stroke }
+  }
+\cs_new_protected:Npn \@@_draw:nnn #1#2#3
+  {
+    \use:c { @@_backend_ #3 _ #1 :n } {#2}
+    \exp_args:Nc \group_insert_after:N { @@_backend_ #3 _ reset: }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Defining named colors}
+%
+% \begin{variable}{\l_@@_named_tl}
+%   Space to store the detail of the named color.
+%    \begin{macrocode}
+\tl_new:N \l_@@_named_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\color_set:nn}
+% \begin{macro}{\@@_set:nnn}
+% \begin{macro}{\@@_set:nn}
+% \begin{macro}{\@@_set:nnw}
+% \begin{macro}{\color_set:nnn, \@@_set_aux:nnn}
+% \begin{macro}{\@@_set_colon:nnw}
+% \begin{macro}{\@@_set_loop:nw}
+% \begin{macro}{\color_set_eq:nn}
+%   Defining named colors means working through the model list and saving
+%   both the \enquote{main} color and any equivalents in other models. Even
+%   if there is only one model, we store a |prop| as well as a |tl|, as there
+%   could be grouping weirdness, etc. When setting using an expression,
+%   we need to avoid any fixed model issues, which is done without a group as
+%   in \pkg{l3keys}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_set:nn #1#2
+  {
+    \exp_args:NV \@@_set:nnn
+      \l_color_fixed_model_tl {#1} {#2}
+  }
+\cs_new_protected:Npn \@@_set:nnn #1#2#3
+  {
+    \tl_clear:N \l_color_fixed_model_tl
+    \@@_set:nn {#2} {#3}
+    \tl_set:Nn \l_color_fixed_model_tl {#1}
+  }
+\cs_new_protected:Npn \@@_set:nn #1#2
+  {
+    \str_if_eq:nnF {#1} { . }
+      {
+        \@@_parse:nN {#2} \l_@@_named_tl
+        \tl_clear_new:c { l_@@_named_ #1 _tl }
+        \tl_set:ce { l_@@_named_ #1 _tl }
+          { \@@_model:N \l_@@_named_tl }
+        \prop_clear_new:c { l_@@_named_ #1 _prop }
+        \prop_put:cve { l_@@_named_ #1 _prop } { l_@@_named_ #1 _tl }
+          { \@@_values:N \l_@@_named_tl }
+        \@@_set:nnw {#1} {#2} #2 ! \s_@@_stop
+      }
+  }
+%    \end{macrocode}
+%   When setting an expression-based color, there could be multiple model
+%   data available for one or more of the input colors. Where that is true for
+%   the \emph{first} named color in an expression, we re-parse the expression
+%   when they are also parameter-based: only |cmyk|, |gray| and |rgb| make
+%   any sense here. There is a bit of a performance hit but this should be
+%   rare and taking place during set-up.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_set:nnw #1#2#3 ! #4 \s_@@_stop
+  {
+    \clist_map_inline:nn { cmyk , gray , rgb }
+      {
+        \prop_get:cnNT { l_@@_named_ #3 _prop } {##1} \l_@@_internal_tl
+          {
+            \prop_if_in:cnF { l_@@_named_ #1 _prop } {##1}
+              {
+                \group_begin:
+                  \bool_set_true:N \l_@@_ignore_error_bool
+                  \tl_set:cn { l_@@_named_ #3 _tl } {##1}
+                  \@@_parse:nN {#2} \l_@@_internal_tl
+                \exp_args:NNNV \group_end:
+                \tl_set:Nn \l_@@_internal_tl \l_@@_internal_tl
+                \prop_put:cee { l_@@_named_ #1 _prop }
+                  { \@@_model:N \l_@@_internal_tl }
+                  { \@@_values:N \l_@@_internal_tl }
+              }
+          }
+      }
+  }
+\cs_new_protected:Npn \color_set:nnn #1#2#3
+  {
+    \str_if_eq:nnF {#1} { . }
+      {
+        \tl_clear_new:c { l_@@_named_ #1 _tl }
+        \prop_clear_new:c { l_@@_named_ #1 _prop }
+        \exp_args:Ne \@@_set_aux:nnn { \tl_to_str:n {#2} }
+          {#1} {#3}
+      }
+  }
+\cs_new_protected:Npe \@@_set_aux:nnn #1#2#3
+  {
+    \exp_not:N \@@_set_colon:nnw {#2} {#3}
+      #1 \c_colon_str \c_colon_str \exp_not:N \s_@@_stop
+  }
+\use:e
+  {
+    \cs_new_protected:Npn \exp_not:N \@@_set_colon:nnw
+      #1#2 #3 \c_colon_str #4 \c_colon_str
+      #5 \exp_not:N \s_@@_stop
+  }
+  {
+    \tl_if_blank:nTF {#4}
+      { \@@_set_loop:nw {#1} #3 }
+      { \@@_set_loop:nw {#1} #4 }
+        / / \s_@@_mark #2 / / \s_@@_stop
+  }
+\cs_new_protected:Npn \@@_set_loop:nw
+  #1#2 / #3 \s_@@_mark #4 / #5 \s_@@_stop
+  {
+    \tl_if_blank:nF {#2}
+      {
+        \@@_select:nnN {#2} {#4} \l_@@_named_tl
+        \tl_set:Ne \l_@@_internal_tl { \@@_model:N \l_@@_named_tl }
+        \tl_if_empty:cT { l_@@_named_ #1 _tl }
+          { \tl_set_eq:cN { l_@@_named_ #1 _tl } \l_@@_internal_tl }
+        \prop_put:cVe { l_@@_named_ #1 _prop } \l_@@_internal_tl
+          { \@@_values:N \l_@@_named_tl }
+        \@@_set_loop:nw {#1} #3 \s_@@_mark #5 \s_@@_stop
+      }
+  }
+\cs_new_protected:Npn \color_set_eq:nn #1#2
+  {
+    \color_if_exist:nTF {#2}
+      {
+        \tl_clear_new:c { l_@@_named_ #1 _tl }
+        \prop_clear_new:c { l_@@_named_ #1 _prop }
+        \str_if_eq:nnTF {#2} { . }
+          {
+            \tl_set:ce { l_@@_named_ #1 _tl }
+              { \@@_model:N \l_@@_current_tl }
+            \prop_put:cve { l_@@_named_ #1 _prop } { l_@@_named_ #1 _tl }
+              { \@@_values:N \l_@@_current_tl }
+          }
+          {
+            \tl_set_eq:cc { l_@@_named_ #1 _tl } { l_@@_named_ #2 _tl }
+            \prop_set_eq:cc { l_@@_named_ #1 _prop } { l_@@_named_ #2 _prop }
+          }
+      }
+      {
+        \msg_error:nnn { color } { unknown-color } {#2}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% A small set of colors are always defined.
+%    \begin{macrocode}
+\color_set:nnn { black } { gray } { 0 }
+\color_set:nnn { white } { gray } { 1 }
+\color_set:nnn { cyan }    { cmyk } { 1 , 0 , 0 , 0 }
+\color_set:nnn { magenta } { cmyk } { 0 , 1 , 0 , 0 }
+\color_set:nnn { yellow }  { cmyk } { 0 , 0 , 1 , 0 }
+\color_set:nnn { red }   { rgb } { 1 , 0 , 0 }
+\color_set:nnn { green } { rgb } { 0 , 1 , 0 }
+\color_set:nnn { blue }  { rgb } { 0 , 0 , 1 }
+%    \end{macrocode}
+%
+% \begin{variable}{\l_@@_named_._prop, \l_@@_named_._tl}
+%   A special named color: this is always defined though not fixed in
+%   definition.
+%    \begin{macrocode}
+\prop_new:c { l_@@_named_._prop }
+\tl_new:c { l_@@_named_._tl }
+\tl_set:ce { l_@@_named_._tl } { \@@_model:N \l_@@_current_tl }
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Exporting colors}
+%
+% \begin{macro}{\color_export:nnN}
+% \begin{macro}{\color_export:nnnN}
+% \begin{macro}{\@@_export:nN}
+% \begin{macro}{\@@_export:nnnN}
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_export:nnN #1#2#3
+  {
+    \group_begin:
+      \tl_if_exist:cT { c_@@_export_ #2 _tl }
+        { \tl_set_eq:Nc \l_color_fixed_model_tl { c_@@_export_ #2 _tl } }
+      \@@_parse:nN {#1} #3
+      \@@_export:nN {#2} #3
+    \exp_args:NNNV \group_end:
+    \tl_set:Nn #3 #3
+  }
+\cs_new_protected:Npn \color_export:nnnN #1#2#3#4
+  {
+    \@@_select_main:Nw #4
+      #1 / / \s_@@_mark #2 / / \s_@@_stop
+    \@@_export:nN {#3} #4
+  }
+\cs_new_protected:Npn \@@_export:nN #1#2
+  { \exp_after:wN \@@_export:nnnN #2 {#1} #2 }
+\cs_new:Npn \@@_export:nnnN #1#2#3#4
+  {
+    \cs_if_exist_use:cF { @@_export_format_ #3 :nnN }
+      {
+        \msg_error:nnn { color } { unknown-export-format } {#3}
+        \use_none:nnn
+      }
+        {#1} {#2} #4
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_export_format_backend:nnN}
+%   Simple.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_export_format_backend:nnN #1#2#3
+  { \tl_set:Nn #3 { {#1} {#2} } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_export:nnnNN}
+%   A generic auxiliary for cases where only one model is appropriate.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_export:nnnNN #1#2#3#4#5
+  {
+    \str_if_eq:nnTF {#2} {#1}
+      { #5 #4 #3 \s_@@_stop }
+      {
+        \@@_convert:nnnN {#2} {#1} {#3} #4
+        \exp_after:wN #5 \exp_after:wN #4
+          #4 \s_@@_stop
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}
+%   {
+%     \c_@@_export_comma-sep-cmyk_tl ,
+%     \c_@@_export_comma-sep-rgb_tl  ,
+%     \c_@@_export_HTML_tl           ,
+%     \c_@@_export_space-sep-cmyk_tl ,
+%     \c_@@_export_space-sep-rgb_tl
+%   }
+%    \begin{macrocode}
+\tl_const:cn { c_@@_export_comma-sep-cmyk_tl } { cmyk }
+\tl_const:cn { c_@@_export_comma-sep-rgb_tl } { rgb }
+\tl_const:Nn \c_@@_export_HTML_tl { rgb }
+\tl_const:cn { c_@@_export_space-sep-cmyk_tl } { cmyk }
+\tl_const:cn { c_@@_export_space-sep-rgb_tl } { rgb }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+%   {
+%     \@@_export_format_comma-sep-cmyk:nnN ,
+%     \@@_export_format_comma-sep-rgb:nnN  ,
+%     \@@_export_format_space-sep-cmyk:nnN ,
+%     \@@_export_format_space-sep-rgb:nnN
+%   }
+%    \begin{macrocode}
+\group_begin:
+  \cs_set_protected:Npn \@@_tmp:w #1#2
+    {
+      \cs_new_protected:cpe { @@_export_format_ #1 :nnN } ##1##2##3
+        {
+          \exp_not:N \@@_export:nnnNN {#2} {##1} {##2} ##3
+            \exp_not:c { @@_export_ #1 :Nw }
+        }
+    }
+  \@@_tmp:w { comma-sep-cmyk } { cmyk }
+  \@@_tmp:w { comma-sep-rgb }  { rgb }
+  \@@_tmp:w { HTML }           { rgb }
+  \@@_tmp:w { space-sep-cmyk } { cmyk }
+  \@@_tmp:w { space-sep-rgb }  { rgb }
+
+\group_end:
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_export_space-sep-cmyk:Nw, \@@_export_comma-sep-cmyk:Nw}
+%    \begin{macrocode}
+\cs_new_protected:cpn { @@_export_comma-sep-cmyk:Nw }
+  #1#2 ~ #3 ~ #4 ~ #5 \s_@@_stop
+  { \tl_set:Nn #1 { #2 , #3 , #4 , #5 } }
+\cs_new_protected:cpn { @@_export_space-sep-cmyk:Nw } #1#2 \s_@@_stop
+  { \tl_set:Nn #1 {#2} }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \@@_export_comma-sep-rgb:Nw ,
+%     \@@_export_HTML:Nw          ,
+%     \@@_export_space-sep-rgb:Nw
+%   }
+% \begin{macro}[EXP]{\@@_export_HTML:n}
+%   \textsc{html} values must be given in |rgb|: we force conversion if
+%   required, then do some simple maths.
+%    \begin{macrocode}
+\cs_new_protected:cpn { @@_export_comma-sep-rgb:Nw } #1#2 ~ #3 ~ #4 \s_@@_stop
+  { \tl_set:Ne #1 { #2 , #3 , #4 } }
+\cs_new_protected:Npn \@@_export_HTML:Nw #1#2 ~ #3 ~ #4 \s_@@_stop
+  {
+    \tl_set:Ne #1
+      {
+        \@@_export_HTML:n {#2}
+        \@@_export_HTML:n {#3}
+        \@@_export_HTML:n {#4}
+      }
+  }
+\cs_new:Npn \@@_export_HTML:n #1
+  {
+    \fp_compare:nNnTF {#1} = { 0 }
+      { 00 }
+      {
+        \fp_compare:nNnT { #1 * 255 } < { 16 } { 0 }
+        \int_to_Hex:n { \fp_to_int:n { #1 * 255 } }
+      }
+  }
+\cs_new_protected:cpn { @@_export_space-sep-rgb:Nw } #1#2 \s_@@_stop
+  { \tl_set:Nn #1 {#2} }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Additional color models}
+%
+% \begin{variable}{\l_@@_internal_prop}
+%    \begin{macrocode}
+\prop_new:N \l_@@_internal_prop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_model_int}
+%   A tracker for the total number of new models.
+%    \begin{macrocode}
+\int_new:N \g_@@_model_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {\c_@@_fallback_cmyk_tl, \c_@@_fallback_gray_tl, \c_@@_fallback_rgb_tl}
+%   For every colorspace, we define one of the base colorspaces as a fallback.
+%   The base colorspaces themselves are their own fallback.
+%    \begin{macrocode}
+\tl_const:Nn \c_@@_fallback_cmyk_tl { cmyk }
+\tl_const:Nn \c_@@_fallback_gray_tl { gray }
+\tl_const:Nn \c_@@_fallback_rgb_tl { rgb }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_colorants_prop}
+%   Mapping from names to colorants.
+%    \begin{macrocode}
+\prop_new:N \g_@@_colorants_prop
+\prop_gput:Nnn \g_@@_colorants_prop { black }   { Black }
+\prop_gput:Nnn \g_@@_colorants_prop { blue }    { Blue }
+\prop_gput:Nnn \g_@@_colorants_prop { cyan }    { Cyan }
+\prop_gput:Nnn \g_@@_colorants_prop { green }   { Green }
+\prop_gput:Nnn \g_@@_colorants_prop { magenta } { Magenta }
+\prop_gput:Nnn \g_@@_colorants_prop { none }    { None }
+\prop_gput:Nnn \g_@@_colorants_prop { red }     { Red }
+\prop_gput:Nnn \g_@@_colorants_prop { yellow }  { Yellow }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {
+%     \c_@@_model_whitepoint_CIELAB_a_tl   ,
+%     \c_@@_model_whitepoint_CIELAB_b_tl   ,
+%     \c_@@_model_whitepoint_CIELAB_e_tl   ,
+%     \c_@@_model_whitepoint_CIELAB_d50_tl ,
+%     \c_@@_model_whitepoint_CIELAB_d55_tl ,
+%     \c_@@_model_whitepoint_CIELAB_d65_tl ,
+%     \c_@@_model_whitepoint_CIELAB_d75_tl
+%   }
+%   Whitepoint data for the CIELAB profiles.
+%    \begin{macrocode}
+\tl_const:Nn \c_@@_model_whitepoint_CIELAB_a_tl      { 1.0985 ~ 1 ~ 0.3558 }
+\tl_const:Nn \c_@@_model_whitepoint_CIELAB_b_tl      { 0.9807 ~ 1 ~ 1.1822 }
+\tl_const:Nn \c_@@_model_whitepoint_CIELAB_e_tl      { 1 ~ 1 ~ 1 }
+\tl_const:cn { c_@@_model_whitepoint_CIELAB_d50_tl } { 0.9642 ~ 1 ~ 0.8251 }
+\tl_const:cn { c_@@_model_whitepoint_CIELAB_d55_tl } { 0.9568 ~ 1 ~ 0.9214 }
+\tl_const:cn { c_@@_model_whitepoint_CIELAB_d65_tl } { 0.9504 ~ 1 ~ 1.0888 }
+\tl_const:cn { c_@@_model_whitepoint_CIELAB_d75_tl } { 0.9497 ~ 1 ~ 1.2261 }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_@@_model_range_CIELAB_tl}
+%   The range for CIELAB color spaces.
+%    \begin{macrocode}
+\tl_const:Nn \c_@@_model_range_CIELAB_tl { 0 ~ 100 ~ -128 ~ 127 ~ -128 ~ 127 }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_alternative_model_prop}
+%   For tracking the alternative model set up for separations, etc.
+%    \begin{macrocode}
+\prop_new:N \g_@@_alternative_model_prop
+\clist_map_inline:nn { cyan , magenta , yellow , black }
+  { \prop_gput:Nnn \g_@@_alternative_model_prop {#1} { cmyk } }
+\clist_map_inline:nn { red , green , blue }
+  { \prop_gput:Nnn \g_@@_alternative_model_prop {#1} { rgb } }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_alternative_values_prop}
+%   Same for the values: a bit more involved.
+%    \begin{macrocode}
+\prop_new:N \g_@@_alternative_values_prop
+\prop_gput:Nnn \g_@@_alternative_values_prop { cyan }    {  1 , 0 , 0 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { magenta } {  0 , 1 , 0 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { yellow }  {  0 , 0 , 1 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { black }   {  0 , 0 , 0 , 1 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { red }   {  1 , 0 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { green } {  0 , 1 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { blue }  {  0 , 0 , 1 }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\color_model_new:nnn, \@@_model_new:nnn}
+%   Set up a new model: in general this has to be handled by a family-dependent
+%   function. To avoid some \enquote{interesting} questions with casing, we
+%   fold the case of the family name. The key--value list should always be
+%   present, so we convert it up-front to a |prop|, then deal with the detail
+%   on a per-family basis.
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_model_new:nnn #1#2#3
+  {
+    \exp_args:Nee \@@_model_new:nnn
+      { \tl_to_str:n {#1} }
+      { \str_casefold:n {#2} } {#3}
+  }
+\cs_new_protected:Npn \@@_model_new:nnn #1#2#3
+  {
+    \cs_if_exist:cTF { @@_parse_model_ #1 :w }
+      {
+        \msg_error:nnn { color } { model-already-defined } {#1}
+      }
+      {
+        \cs_if_exist:cTF { @@_model_ #2 :n }
+          {
+            \prop_set_from_keyval:Nn \l_@@_internal_prop {#3}
+            \use:c { @@_model_ #2 :n } {#1}
+          }
+          {
+            \msg_error:nnn { color } { unknown-model-type } {#2}
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_model_init:nnn, \@@_model_init:nne}
+%   A shared auxiliary to do the basics of setting up a new model: reserve a
+%   number, create a white-equivalent, set up links to the backend.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_init:nnn #1#2#3
+  {
+    \int_gincr:N \g_@@_model_int
+    \clist_map_inline:nn { fill , stroke , select }
+      {
+        \cs_new_protected:cpe { @@_backend_ ##1 _ #1 :n } ####1
+          {
+            \exp_not:c { @@_backend_ ##1 _ #2 :nn }
+              { color \int_use:N \g_@@_model_int } {####1}
+          }
+      }
+    \cs_new_protected:cpe { @@_model_ #1 _white: }
+      {
+        \prop_put:Nnn \exp_not:N \l_@@_named_white_prop {#1}
+          { \exp_not:n {#3} }
+        \exp_not:N \int_compare:nNnF { \tex_currentgrouplevel:D } = 0
+          { \group_insert_after:N \exp_not:c { @@_model_ #1 _ white: } }
+      }
+    \use:c { @@_model_ #1 _white: }
+  }
+\cs_generate_variant:Nn \@@_model_init:nnn { nne }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_model_separation:n}
+% \begin{macro}{\@@_model_separation:nn}
+% \begin{macro}{\@@_model_separation:nnn}
+% \begin{macro}{\@@_model_separation:w}
+% \begin{macro}
+%   {
+%     \@@_model_separation_cmyk:nnnnnn ,
+%     \@@_model_separation_gray:nnnnnn ,
+%     \@@_model_separation_rgb:nnnnnn
+%   }
+% \begin{macro}{\@@_model_convert:nnn}
+% \begin{macro}{\@@_model_separation_CIELAB:nnnnnn}
+% \begin{macro}{\@@_model_separation_CIELAB:nnnnnnn}
+%   Separations must have a \enquote{real} name, which is pretty easy to find.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_separation:n #1
+  {
+    \prop_get:NnNTF \l_@@_internal_prop { name }
+      \l_@@_internal_tl
+      {
+        \exp_args:NV \@@_model_separation:nn
+          \l_@@_internal_tl {#1}
+      }
+      {
+        \msg_error:nnn { color }
+          { separation-requires-name } {#1}
+      }
+  }
+%    \end{macrocode}
+%   We have two keys to find at this stage: the alternative space model
+%   and linked values.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_separation:nn #1#2
+  {
+    \prop_get:NnNTF \l_@@_internal_prop { alternative-model }
+      \l_@@_internal_tl
+      {
+        \exp_args:NV \@@_model_separation:nnn
+          \l_@@_internal_tl {#2} {#1}
+      }
+      {
+        \msg_error:nnn { color }
+          { separation-alternative-model } {#2}
+      }
+  }
+\cs_new_protected:Npn \@@_model_separation:nnn #1#2#3
+  {
+    \cs_if_exist:cTF { @@_model_separation_ #1 :nnnnnn }
+      {
+        \prop_get:NnNTF \l_@@_internal_prop { alternative-values }
+          \l_@@_internal_tl
+          {
+            \exp_after:wN \@@_model_separation:w \l_@@_internal_tl
+              , 0 , 0 , 0 , 0 \s_@@_stop {#2} {#3} {#1}
+          }
+          {
+            \msg_error:nnn { color }
+              { separation-alternative-values } {#2}
+          }
+      }
+      {
+        \msg_error:nnn { color }
+          { unknown-alternative-model } {#1}
+      }
+  }
+%    \end{macrocode}
+%   As each alternative space leads to a different requirement for conversion,
+%   and as there are only a small number of choices, we manually split the data
+%   and then set up. Notice that mixing tints is really just the same
+%   as mixing \texttt{gray}. The \texttt{white} color is special, as it allows
+%   tints to be adjusted without an additional color space. To make sure the
+%   data is set for that at all group levels, we need to work on a per-level
+%   basis. Within the output, only the set-up needs the \enquote{real} name
+%   of the colorspace: we use a simple tracking number for general usage
+%   as this is a clear namespace without issues of escaping chars.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_separation:w
+  #1 , #2 , #3 , #4 , #5 \s_@@_stop #6#7#8
+  {
+    \@@_model_init:nnn {#6} { separation } { 0 }
+    \cs_new_eq:cN { @@_parse_mix_ #6 :nw } \@@_parse_mix_gray:nw
+    \cs_new:cpn { @@_parse_model_ #6 :w } ##1 , ##2 \s_@@_stop
+      { {#6} { \@@_parse_number:n {##1} } }
+    \use:c { @@_model_separation_ #8 :nnnnnn }
+      {#6} {#7} {#1} {#2} {#3} {#4}
+    \prop_gput:Nnn \g_@@_alternative_model_prop {#6} {#8}
+    \prop_gput:Nne \g_@@_colorants_prop {#6}
+      { \str_convert_pdfname:n {#7} }
+  }
+\cs_new_protected:Npn \@@_model_separation_cmyk:nnnnnn #1#2#3#4#5#6
+  {
+    \tl_const:cn { c_@@_fallback_ #1 _tl } { cmyk }
+    \cs_new:cpn { @@_convert_ #1 _cmyk:w } ##1 \s_@@_stop
+      {
+        \fp_eval:n {##1 * #3} ~
+        \fp_eval:n {##1 * #4} ~
+        \fp_eval:n {##1 * #5} ~
+        \fp_eval:n {##1 * #6}
+      }
+    \cs_new:cpn { @@_convert_cmyk_ #1 :w } ##1 \s_@@_stop { 1 }
+    \prop_gput:Nnn \g_@@_alternative_values_prop {#1} { #3 , #4 , #5 , #6 }
+    \@@_backend_separation_init:nnnnn {#2} { /DeviceCMYK } { }
+      { 0 ~ 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 ~ #6 }
+  }
+\cs_new_protected:Npn \@@_model_separation_rgb:nnnnnn #1#2#3#4#5#6
+  {
+    \tl_const:cn { c_@@_fallback_ #1 _tl } { rgb }
+    \cs_new:cpn { @@_convert_ #1 _rgb:w } ##1 \s_@@_stop
+      {
+        \fp_eval:n {##1 * #3} ~
+        \fp_eval:n {##1 * #4} ~
+        \fp_eval:n {##1 * #5}
+      }
+    \cs_new:cpn { @@_convert_rgb_ #1 :w } ##1 \s_@@_stop { 1 }
+    \prop_gput:Nnn \g_@@_alternative_values_prop {#1} { #3 , #4 , #5 }
+    \@@_backend_separation_init:nnnnn {#2} { /DeviceRGB } { }
+      { 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 }
+  }
+\cs_new_protected:Npn \@@_model_separation_gray:nnnnnn #1#2#3#4#5#6
+  {
+    \tl_const:cn { c_@@_fallback_ #1 _tl } { gray }
+    \cs_new:cpn { @@_convert_ #1 _gray:w } ##1 \s_@@_stop
+      { \fp_eval:n {##1 * #3} }
+    \cs_new:cpn { @@_convert_gray_ #1 :w } ##1 \s_@@_stop { 1 }
+    \prop_gput:Nnn \g_@@_alternative_values_prop {#1} {#3}
+    \@@_backend_separation_init:nnnnn {#2} { /DeviceGray } { } { 0 } {#3}
+  }
+%    \end{macrocode}
+%   Generic model conversion \emph{via} an alternative intermediate.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_convert:nnn #1#2#3
+  {
+    \cs_new:cpe { @@_convert_ #1 _ #3 :w } ##1 \s_@@_stop
+      {
+        \exp_not:N \exp_args:NNe \exp_not:N \use:nn
+        \exp_not:c { @@_convert_  #2 _ #3 :w }
+          { \exp_not:c { @@_convert_ #1 _ #2 :w } ##1 \s_@@_stop }
+          \c_space_tl \exp_not:N \s_@@_stop
+      }
+  }
+%    \end{macrocode}
+%   Setting up for CIELAB needs a bit more work: there is the illuminant and
+%   the need for an appropriate object.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_separation_CIELAB:nnnnnn #1#2#3#4#5#6
+  {
+    \prop_get:NnNF \l_@@_internal_prop { illuminant }
+      \l_@@_internal_tl
+      {
+        \msg_error:nnn { color }
+          { CIELAB-requires-illuminant } {#1}
+        \tl_set:Nn \l_@@_internal_tl { d50 }
+      }
+    \exp_args:NV \@@_model_separation_CIELAB:nnnnnnn
+      \l_@@_internal_tl {#1} {#2} {#3} {#4} {#5} {#6}
+  }
+%    \end{macrocode}
+%   If a CIELAB space is being set up, we need the illuminant, then create
+%   the appropriate set up. At present, this doesn't include \texttt{BlackPoint}
+%   or \texttt{Range} data, but that may be added later. As CIELAB colors
+%   cannot be converted to anything else, we fallback to producing black in the
+%   gray colorspace: the user should set up a second model for colors set up this way.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_separation_CIELAB:nnnnnnn #1#2#3#4#5#6#7
+  {
+    \tl_if_exist:cTF { c_@@_model_whitepoint_CIELAB_ #1 _tl }
+      {
+        \@@_backend_separation_init_CIELAB:nnn {#1} {#3} { #4 ~ #5 ~ #6 }
+        \tl_const:cn { c_@@_fallback_ #2 _tl } { gray }
+        \cs_new:cpn { @@_convert_ #2 _gray:w } ##1 \s_@@_stop
+          { 0 }
+        \cs_new:cpn { @@_convert_gray_ #2 :w } ##1 \s_@@_stop
+          { 1 }
+      }
+      {
+        \msg_error:nnn { color }
+          { unknown-CIELAB-illuminant } {#1}
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_model_devicen:n}
+% \begin{macro}{\@@_model_devicen:nn}
+% \begin{macro}{\@@_model_devicen:nnn}
+% \begin{macro}{\@@_model_devicen:nnnn}
+% \begin{macro}
+%   {
+%     \@@_model_devicen_parse_1:nn ,
+%     \@@_model_devicen_parse_2:nn ,
+%     \@@_model_devicen_parse_3:nn ,
+%     \@@_model_devicen_parse_4:nn ,
+%     \@@_model_devicen_parse_generic:nn
+%  }
+%  \begin{macro}[EXP]{\@@_model_devicen_parse:nw}
+%  \begin{macro}[EXP]{\@@_model_devicen_mix:nw}
+% \begin{macro}{\@@_model_devicen_init:nnn}
+% \begin{macro}{\@@_model_devicen_init:nnnn}
+% \begin{macro}{\@@_model_devicen_tranform:w}
+% \begin{macro}
+%   {
+%     \@@_model_devicen_tranform_1:nnnnn ,
+%     \@@_model_devicen_tranform_3:nnnnn ,
+%     \@@_model_devicen_tranform_4:nnnnn ,
+%   }
+% \begin{macro}{\@@_model_devicen_tranform:nnn}
+% \begin{macro}[EXP]{\@@_model_devicen_colorant:n}
+% \begin{macro}{\@@_model_devicen_convert:nnn}
+% \begin{macro}
+%   {
+%     \@@_model_devicen_convert_cmyk:n ,
+%     \@@_model_devicen_convert_gray:n ,
+%     \@@_model_devicen_convert_rgb:n
+%   }
+% \begin{macro}{\@@_model_devicen_convert:nnnn}
+% \begin{macro}[EXP]{\@@_model_devicen_convert:n, \@@_model_devicen_convert_aux:n}
+% \begin{macro}[EXP]{\@@_model_devicen_convert:w}
+% \begin{macro}[EXP]{\@@_convert_devicen_cmyk:nnnnw}
+% \begin{macro}[EXP]{\@@_convert_devicen_cmyk:nnnnnnnnn}
+% \begin{macro}[EXP]{\@@_convert_devicen_cmyk_aux:nnnnw}
+% \begin{macro}[EXP]{\@@_convert_devicen_gray:nw}
+% \begin{macro}[EXP]{\@@_convert_devicen_gray:nnn}
+% \begin{macro}[EXP]{\@@_convert_devicen_gray_aux:nw}
+% \begin{macro}[EXP]{\@@_convert_devicen_rgb:nnnw}
+% \begin{macro}[EXP]{\@@_convert_devicen_rgb:nnnnnnn}
+% \begin{macro}[EXP]{\@@_convert_devicen_rgb_aux:nnnw}
+%   We require a list of component names here: one might call them colorants,
+%   but it's convenient to use \TeX{} names instead so we slightly adjust the
+%   terminology.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen:n #1
+  {
+    \prop_get:NnNTF \l_@@_internal_prop { names }
+      \l_@@_internal_tl
+      {
+        \exp_args:NV \@@_model_devicen:nn
+          \l_@@_internal_tl {#1}
+      }
+      {
+        \msg_error:nnn { color }
+          { DeviceN-requires-names } {#1}
+      }
+  }
+%    \end{macrocode}
+%   All valid models will have an alternative listed, either hard-coded for
+%   the core device ones, or dynamically added for Separations, etc.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen:nn #1#2
+  {
+    \tl_clear:N \l_@@_model_tl
+    \clist_map_inline:nn {#1}
+      {
+        \prop_get:NnNTF \g_@@_alternative_model_prop {##1}
+          \l_@@_internal_tl
+          {
+            \tl_if_empty:NTF \l_@@_model_tl
+              { \tl_set_eq:NN \l_@@_model_tl \l_@@_internal_tl }
+              {
+                \str_if_eq:VVF \l_@@_model_tl \l_@@_internal_tl
+                  {
+                    \msg_error:nnn { color }
+                      { DeviceN-inconsistent-alternative }
+                      {#2}
+                    \clist_map_break:n { \use_none:nnnn }
+                  }
+              }
+          }
+          {
+            \str_if_eq:nnF {##1} { none }
+              {
+                \msg_error:nnn { color }
+                  { DeviceN-no-alternative }
+                  {#2}
+              }
+          }
+      }
+    \tl_if_empty:NTF \l_@@_model_tl
+      {
+        \msg_error:nnn { color }
+          { DeviceN-no-alternative } {#2}
+      }
+      { \exp_args:NV \@@_model_devicen:nnn \l_@@_model_tl {#1} {#2} }
+  }
+%    \end{macrocode}
+%   We now complete the data we require by first finding out how many
+%   colorants there are, then moving on to begin constructing the function
+%   required to map to the alternative color space.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen:nnn #1#2#3
+  {
+    \exp_args:Ne \@@_model_devicen:nnnn
+      { \clist_count:n {#2} } {#1} {#2} {#3}
+  }
+%    \end{macrocode}
+%   At this stage, we have checked everything is in place, so we can set up
+%   the \TeX{} and backend data structures. As for separations, it's not really
+%   possible in general to have a fallback, so we simply provide
+%   \enquote{black} for each element.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen:nnnn #1#2#3#4
+  {
+    \@@_model_init:nne {#4} { devicen }
+      {
+        0 \prg_replicate:nn { #1 - 1 } { ~ 0 }
+      }
+    \cs_if_exist_use:cF { @@_model_devicen_parse_ #1 :nn }
+      { \@@_model_devicen_parse_generic:nn }
+        {#4} {#1}
+    \@@_model_devicen_init:nnn {#1} {#2} {#3}
+    \@@_model_devicen_convert:nnne {#4} {#2} {#3}
+      {
+        1 \prg_replicate:nn { #1 - 1 } { ~ 1 }
+      }
+  }
+%    \end{macrocode}
+%   For short lists of DeviceN colors, we can use hand-tuned parsing. This
+%   lines up with other models, where we allow for up to four components. For
+%   larger spaces, rather than limit artificially, we use a somewhat slow
+%   approach based on open-ended commas-lists.
+%    \begin{macrocode}
+\cs_new_protected:cpn { @@_model_devicen_parse_1:nn } #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  } ##1 , ##2 \s_@@_stop
+      { {#1} { \@@_parse_number:n {##1} } }
+    \cs_new_eq:cN { @@_parse_mix_ #1 :nw  } \@@_parse_mix_gray:nw
+  }
+\cs_new_protected:cpn { @@_model_devicen_parse_2:nn } #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  } ##1 , ##2 , ##3 \s_@@_stop
+      { {#1} { \@@_parse_number:n {##1} ~ \@@_parse_number:n {##2} } }
+    \cs_new:cpn { @@_parse_mix_ #1 :nw }
+      ##1##2 ~ ##3 \s_@@_mark ##4 ~ ##5 \s_@@_stop
+      {
+        \fp_eval:n { ##2 * ##1 + ##4 * ( 1 - ##1 ) } \c_space_tl
+        \fp_eval:n { ##3 * ##1 + ##5 * ( 1 - ##1 ) }
+      }
+  }
+\cs_new_protected:cpn { @@_model_devicen_parse_3:nn } #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  } ##1 , ##2 , ##3 , ##4 \s_@@_stop
+      {
+        {#1}
+        {
+          \@@_parse_number:n {##1} ~
+          \@@_parse_number:n {##2} ~
+          \@@_parse_number:n {##3}
+        }
+      }
+    \cs_new_eq:cN { @@_parse_mix_ #1 :nw  } \@@_parse_mix_rgb:nw
+  }
+\cs_new_protected:cpn { @@_model_devicen_parse_4:nn } #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  }
+      ##1 , ##2 , ##3 , ##4 , ##5 \s_@@_stop
+      {
+        {#1}
+        {
+          \@@_parse_number:n {##1} ~
+          \@@_parse_number:n {##2} ~
+          \@@_parse_number:n {##3} ~
+          \@@_parse_number:n {##4}
+        }
+      }
+  \cs_new_eq:cN { @@_parse_mix_ #1 :nw } \@@_parse_mix_cmyk:nw
+  }
+\cs_new_protected:Npn \@@_model_devicen_parse_generic:nn #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  } ##1 , ##2 \s_@@_stop
+      {
+        {#1}
+        { \@@_model_devicen_parse:nw {#2} ##1 , ##2 , \q_nil , \s_@@_stop }
+      }
+    \cs_new:cpe { @@_parse_mix_ #1 :nw }
+      ##1 ##2 \s_@@_mark ##3 \s_@@_stop
+      {
+        \exp_not:N \@@_model_devicen_mix:nw {##1}
+          ##2 \c_space_tl \exp_not:N \q_nil \c_space_tl \exp_not:N \s_@@_mark
+          ##3 \c_space_tl \exp_not:N \q_nil \c_space_tl \exp_not:N \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_model_devicen_parse:nw #1#2 , #3 \s_@@_stop
+  {
+    \int_compare:nNnT {#1} > 0
+      {
+        \quark_if_nil:nTF {#2}
+          { \prg_replicate:nn {#1} { 0 ~ } }
+          {
+            \@@_parse_number:n {#2}
+            \int_compare:nNnT {#1} > 1 { ~ }
+            \exp_args:Nf \@@_model_devicen_parse:nw
+              { \int_eval:n { #1 - 1 } } #3 \s_@@_stop
+          }
+      }
+  }
+\cs_new:Npn \@@_model_devicen_mix:nw #1#2 ~ #3 \s_@@_mark #4 ~ #5 \s_@@_stop
+  {
+    \fp_eval:n { #2 * #1 + #4 * ( 1 - #1 ) }
+    \quark_if_nil:oF { \tl_head:w #3 \q_stop }
+      {
+        \c_space_tl
+        \@@_model_devicen_mix:nw {#1} #3 \s_@@_mark #5 \s_@@_stop
+      }
+  }
+%    \end{macrocode}
+%   To construct the tint transformation, we have to use PostScript. The
+%   aim is to have the final tint for each device colorant as
+%   \[
+%     1 - \prod_{n} (1 - X_{n} D_{X_{n}})
+%   \]
+%   where $X$ is a DeviceN colorant and $D$ is the amount of device colorant
+%   that the DeviceN colorant maps to. At the start of the process, the
+%   PostScript stack will contain the $X_{n}$ values, whilst we have the
+%   $D$ values on a per-DeviceN colorant basis. The more convenient approach
+%   for us is therefore to take each DeviceN colorant in turn and find the
+%   value $1 - X_{n} D_{X_{n}}$, multiplying as we go, and finalise with the
+%   subtraction. That contrasts to \pkg{colorspace}: it splits the process
+%   up by process color, which works better when you have a fixed list
+%   of colorants. (\pkg{colorspace} only supports up to $4$ DeviceN colors,
+%   and only \texttt{cmyk} as the alternative space.) To set this up,
+%   we first need to know the number of values in the target color space:
+%   this is easily handled as there are a very small range of possibles.
+%   Once we have that information, it's relatively easy to build the required
+%   PostScript using some generic code.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen_init:nnn #1#2#3
+  {
+    \exp_args:Ne \@@_model_devicen_init:nnnn
+      {
+        \str_case:nn {#2}
+          {
+            { cmyk } { 4 }
+            { gray } { 1 }
+            { rgb }  { 3 }
+          }
+      }
+      {#1} {#2} {#3}
+  }
+%    \end{macrocode}
+%   As we always need to split the alternative values into parts, we use a
+%   shared auxiliary and only use a minimal difference between code paths.
+%   Construction of the tint transformation is as far as possible done using
+%   loops, which means there are some inefficiencies for device colors in
+%   the \texttt{DeviceN} space: we roll the stack one-at-a-time even if there
+%   is a potential shortcut. However, that way there is nothing to special-case.
+%   Once this is sorted, we can write the tint transform object, which will
+%   remain as the last object until we sort out the final step: the colorant
+%   list.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen_init:nnnn #1#2#3#4
+  {
+    \tl_set:Ne \l_@@_internal_tl
+      { \prg_replicate:nn {#1} { 1.0 ~ }   }
+    \int_zero:N \l_@@_internal_int
+    \clist_map_inline:nn {#4}
+      {
+        \int_incr:N \l_@@_internal_int
+        \prop_get:NnN \g_@@_alternative_values_prop {##1}
+          \l_@@_value_tl
+        \exp_after:wN \@@_model_devicen_transform:w
+          \l_@@_value_tl , 0 , 0 , 0 , \s_@@_stop {#1} {#2}
+      }
+    \tl_put_right:Ne \l_@@_internal_tl
+      {
+        \prg_replicate:nn {#1}
+          { neg ~ 1.0 ~ add ~ #1 ~ -1 ~ roll ~ }
+        \int_eval:n { #2 + #1 } ~ #1 ~ roll
+        \prg_replicate:nn {#2} { ~ pop } ~
+        #1 ~ 1 ~ roll
+      }
+    \use:e
+      {
+        \@@_backend_devicen_init:nnn
+          {
+            \clist_map_function:nN {#4}
+              \@@_model_devicen_colorant:n
+          }
+          {
+            \str_case:nn {#3}
+              {
+                { cmyk } { /DeviceCMYK }
+                { gray } { /DeviceGray }
+                { rgb }  { /DeviceRGB }
+              }
+          }
+          { \exp_not:V \l_@@_internal_tl }
+      }
+  }
+\cs_new_protected:Npn \@@_model_devicen_transform:w
+  #1 , #2 , #3 , #4 , #5 \s_@@_stop #6#7
+  {
+    \use:c { @@_model_devicen_transform_ #6 :nnnnn }
+      {#1} {#2} {#3} {#4} {#7}
+  }
+\cs_new_protected:cpn { @@_model_devicen_transform_1:nnnnn } #1#2#3#4#5
+  { \@@_model_devicen_transform:nnn {#5} { 1 } {#1} }
+\cs_new_protected:cpn { @@_model_devicen_transform_3:nnnnn } #1#2#3#4#5
+  {
+    \clist_map_inline:nn { #1 , #2 , #3 }
+      { \@@_model_devicen_transform:nnn {#5} { 3 } {##1} }
+  }
+\cs_new_protected:cpn { @@_model_devicen_transform_4:nnnnn } #1#2#3#4#5
+  {
+    \clist_map_inline:nn { #1 , #2 , #3 , #4 }
+      { \@@_model_devicen_transform:nnn {#5} { 4 } {##1} }
+  }
+\cs_new_protected:Npn \@@_model_devicen_transform:nnn #1#2#3
+  {
+    \tl_put_right:Ne \l_@@_internal_tl
+      {
+        \fp_compare:nNnF {#3} = \c_zero_fp
+          {
+            \int_eval:n { #1 - \l_@@_internal_int + #2 } ~ index ~
+              -#3 ~ mul ~ 1.0 ~ add ~ mul ~
+          }
+        #2 ~ -1 ~ roll ~
+      }
+  }
+\cs_new:Npn \@@_model_devicen_colorant:n #1
+  {
+    / \prop_item:Nn \g_@@_colorants_prop {#1} ~
+  }
+%    \end{macrocode}
+%   Here we need to set up conversion from the DeviceN space to the alternative
+%   at the \TeX{} level. This also means supplying methods for inter-converting
+%   to other parameter-based spaces. Essentially the approach is exactly the same
+%   as the PostScript, just expressed in \TeX{} terms.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen_convert:nnnn #1#2#3
+  {
+    \use:c { @@_model_devicen_convert_ #2 :nnn } {#1} {#3}
+  }
+\cs_generate_variant:Nn \@@_model_devicen_convert:nnnn { nnne }
+\cs_new_protected:Npn \@@_model_devicen_convert_cmyk:nnn #1#2
+  {
+    \tl_const:cn { c_@@_fallback_ #1 _tl } { cmyk }
+    \@@_model_devicen_convert:nnnnn {#1} { cmyk } { 4 } {#2}
+  }
+\cs_new_protected:Npn \@@_model_devicen_convert_gray:nnn #1#2
+  {
+    \tl_const:cn { c_@@_fallback_ #1 _tl } { gray }
+    \@@_model_devicen_convert:nnnnn {#1} { gray } { 1 } {#2}
+  }
+\cs_new_protected:Npn \@@_model_devicen_convert_rgb:nnn #1#2
+  {
+    \tl_const:cn { c_@@_fallback_ #1 _tl } { rgb }
+    \@@_model_devicen_convert:nnnnn {#1} { rgb } { 3 } {#2}
+  }
+\cs_new_protected:Npn \@@_model_devicen_convert:nnnnn #1#2#3#4#5
+  {
+    \cs_new:cpn { @@_convert_ #2 _ #1 :w } ##1 \s_@@_stop {#5}
+    \cs_new:cpe { @@_convert_ #1 _ #2 :w } ##1 \s_@@_stop
+      {
+        \exp_not:c { @@_convert_devicen_ #2 : \prg_replicate:nn {#3} { n } w }
+          \prg_replicate:nn {#3} { { 1 } }
+          ##1 ~ \exp_not:N \s_@@_mark
+          \clist_map_function:nN {#4} \@@_model_devicen_convert:n
+          {}
+          \exp_not:N \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_model_devicen_convert:n #1
+  {
+    {
+      \exp_args:Ne \@@_model_devicen_convert_aux:n
+        { \prop_item:Nn \g_@@_alternative_values_prop {#1} }
+    }
+  }
+\cs_new:Npn \@@_model_devicen_convert_aux:n #1
+  { \@@_model_devicen_convert_aux:w #1 , , , , \s_@@_stop }
+\cs_new:Npn \@@_model_devicen_convert_aux:w #1 , #2 , #3 , #4 , #5 \s_@@_stop
+  {
+    {#1}
+    \tl_if_blank:nF {#2}
+      {
+        {#2}
+        \tl_if_blank:nF {#3}
+          {
+            {#3}
+            \tl_if_blank:nF {#4} { {#4} }
+          }
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_cmyk:nnnnw
+  #1#2#3#4#5 ~ #6 \s_@@_mark #7#8 \s_@@_stop
+  {
+    \@@_convert_devicen_cmyk:nnnnnnnnn {#5} {#1} {#2} {#3} {#4} #7
+      #6 \s_@@_mark #8 \s_@@_stop
+  }
+\cs_new:Npn \@@_convert_devicen_cmyk:nnnnnnnnn #1#2#3#4#5#6#7#8#9
+  {
+    \use:e
+      {
+        \exp_not:N \@@_convert_devicen_cmyk_aux:nnnnw
+          { \fp_eval:n { #2 * (1 - (#1 * #6)) } }
+          { \fp_eval:n { #3 * (1 - (#1 * #7)) } }
+          { \fp_eval:n { #4 * (1 - (#1 * #8)) } }
+          { \fp_eval:n { #5 * (1 - (#1 * #9)) } }
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_cmyk_aux:nnnnw
+  #1#2#3#4 #5 \s_@@_mark #6 \s_@@_stop
+  {
+    \tl_if_blank:nTF {#5}
+      {
+        \fp_eval:n { 1 - #1 } ~
+        \fp_eval:n { 1 - #2 } ~
+        \fp_eval:n { 1 - #3 } ~
+        \fp_eval:n { 1 - #4 }
+      }
+      {
+        \@@_convert_devicen_cmyk:nnnnw {#1} {#2} {#3} {#4}
+          #5 \s_@@_mark #6 \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_gray:nw
+  #1#2 ~ #3 \s_@@_mark #4#5 \s_@@_stop
+  {
+    \@@_convert_devicen_gray:nnn {#2} {#1} #4
+      #3 \s_@@_mark #5 \s_@@_stop
+  }
+\cs_new:Npn \@@_convert_devicen_gray:nnn #1#2#3
+  {
+    \exp_arsgs:Ne \@@_convert_devicen_gray_aux:nw
+      { \fp_eval:n { #2 * (1 - (#1 * #3)) } }
+  }
+\cs_new:Npn \@@_convert_devicen_gray_aux:nw
+  #1 #2 \s_@@_mark #3 \s_@@_stop
+  {
+    \tl_if_blank:nTF {#2}
+      { \fp_eval:n { 1 - #1 } }
+      {
+        \@@_convert_devicen_gray:nw {#1}
+          #2 \s_@@_mark #3 \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_rgb:nnnw
+  #1#2#3#4 ~ #5 \s_@@_mark #6#7 \s_@@_stop
+  {
+    \@@_convert_devicen_rgb:nnnnnnn {#4} {#1} {#2} {#3} #6
+      #5 \s_@@_mark #7 \s_@@_stop
+  }
+\cs_new:Npn \@@_convert_devicen_rgb:nnnnnnn #1#2#3#4#5#6#7
+  {
+    \use:e
+      {
+        \exp_not:N \@@_convert_devicen_rgb_aux:nnnw
+          { \fp_eval:n { #2 * (1 - (#1 * #5)) } }
+          { \fp_eval:n { #3 * (1 - (#1 * #6)) } }
+          { \fp_eval:n { #4 * (1 - (#1 * #7)) } }
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_rgb_aux:nnnw
+  #1#2#3 #4 \s_@@_mark #5 \s_@@_stop
+  {
+    \tl_if_blank:nTF {#4}
+      {
+        \fp_eval:n { 1 - #1 } ~
+        \fp_eval:n { 1 - #2 } ~
+        \fp_eval:n { 1 - #3 }
+      }
+      {
+        \@@_convert_devicen_rgb:nnnw {#1} {#2} {#3}
+          #4 \s_@@_mark #5 \s_@@_stop
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\c_@@_icc_colorspace_signatures_prop}
+%   The signatures in the ICC file header indicating the underlying
+%   colorspace.  We map it to three values: The number of components,
+%   the values corresponding to white, and the range.
+%    \begin{macrocode}
+\prop_const_from_keyval:Nn \c_@@_icc_colorspace_signatures_prop
+  {
+% Gray
+    47524159 = {1} {1} {0} {},
+% RGB
+    52474220 = {3} {0~0~0} {1~1~1} {},
+% CMYK
+    434D594B = {4} {0~0~0~1} {0~0~0~0} {},
+% Lab
+    4C616220 = {3} {0~0~0} {100~0~0} {0~100~-128~127~-128~127}
+  }
+%    \end{macrocode}
+% \end{variable}
+% \begin{macro}{\@@_model_iccbased:n}
+% \begin{macro}{\@@_model_iccbased:nn}
+% \begin{macro}{\@@_model_iccbased:nnn, \@@_model_iccbased_aux:nnn}
+%   For an ICC profile, we need a file name and a number of components. The
+%   file name is processed here so the backend can treat it as a string.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_iccbased:n #1
+  {
+    \prop_get:NnNTF \l_@@_internal_prop { file }
+      \l_@@_internal_tl
+      {
+        \exp_args:NV \@@_model_iccbased:nn
+          \l_@@_internal_tl {#1}
+      }
+      {
+        \msg_error:nnn { color }
+          { ICCBased-requires-file } {#1}
+      }
+  }
+\cs_new_protected:Npn \@@_model_iccbased:nn #1#2
+  {
+    \prop_get:NeNTF \c_@@_icc_colorspace_signatures_prop
+      { \file_hex_dump:nnn { #1 } { 17 } { 20 } } \l_@@_internal_tl
+      {
+        \exp_last_unbraced:NV \@@_model_iccbased_aux:nnnnnn
+          \l_@@_internal_tl { #2 } { #1 }
+      }
+      {
+        \msg_error:nnn { color }
+        { ICCBased-unsupported-colorspace } {#2}
+      }
+  }
+%    \end{macrocode}
+%   Here, we can use the same internals as for DeviceN approach as we know the
+%   number of components. No conversion is possible, so there is no need
+%   to worry about that at all.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_iccbased_aux:nnnnnn #1#2#3#4#5#6
+  {
+    \@@_model_init:nnn {#5} { iccbased } {#3}
+    \tl_const:cn { c_@@_fallback_ #5 _tl } { gray }
+    \cs_new:cpn { @@_convert_ #5 _gray:w } ##1 \s_@@_stop { 0 }
+    \cs_new:cpn { @@_convert_gray_ #5 :w } ##1 \s_@@_stop { #2 }
+    \use:c { @@_model_devicen_parse_ #1 :nn } {#5} {#1}
+    \exp_args:Ne \@@_backend_iccbased_init:nnn
+      { \file_full_name:n {#6} } {#1} {#4}
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Applying profiles}
+%
+% \begin{macro}{\color_profile_apply:nn, \@@_profile_apply:nn}
+% \begin{macro}
+%   {
+%     \@@_profile_apply_gray:n ,
+%     \@@_profile_apply_rgb:n  ,
+%     \@@_profile_apply_cmyk:n
+%   }
+%   With a limited range of outcomes, this is largely about getting data to the
+%   backend.
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_profile_apply:nn #1#2
+  {
+    \exp_args:Ne \@@_profile_apply:nn
+      { \file_full_name:n {#1} } {#2}
+  }
+\cs_new_protected:Npn \@@_profile_apply:nn #1#2
+  {
+    \cs_if_exist_use:cF { @@_profile_apply_ \tl_to_str:n {#2} :n }
+      {
+        \msg_error:nnn { color } { ICC-Device-unknown } {#2}
+        \use_none:n
+      }
+        {#1}
+  }
+\cs_new_protected:Npn \@@_profile_apply_gray:n #1
+  {
+    \int_gincr:N \g_@@_model_int
+    \@@_backend_iccbased_device:nnn {#1} { Gray } { 1 }
+  }
+\cs_new_protected:Npn \@@_profile_apply_rgb:n #1
+  {
+    \int_gincr:N \g_@@_model_int
+    \@@_backend_iccbased_device:nnn {#1} { RGB } { 3 }
+  }
+\cs_new_protected:Npn \@@_profile_apply_cmyk:n #1
+  {
+    \int_gincr:N \g_@@_model_int
+    \@@_backend_iccbased_device:nnn {#1} { CMYK } { 4 }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Diagnostics}
+%
+% \begin{macro}{\color_show:n, \color_log:n, \@@_show:Nn}
+% \begin{macro}[EXP]{\@@_show:n}
+%   Extract the information about a color and format for the user: the approach
+%   is similar to the keys module here.
+%    \begin{macrocode}
+\cs_new_protected:Npn \color_show:n
+  { \@@_show:Nn \msg_show:nneeee }
+\cs_new_protected:Npn \color_log:n
+  { \@@_show:Nn \msg_log:nneeee }
+\cs_new_protected:Npn \@@_show:Nn #1#2
+  {
+    #1 { color } { show }
+      {#2}
+      {
+        \color_if_exist:nT {#2}
+          {
+            \exp_args:Nv \@@_show:n { l_@@_named_ #2 _tl }
+            \prop_map_function:cN
+              { l_@@_named_ #2 _prop }
+              \msg_show_item_unbraced:nn
+          }
+      }
+      { }
+      { }
+  }
+\cs_new:Npn \@@_show:n #1
+  {
+    \msg_show_item_unbraced:nn { model } {#1}
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+%    \begin{macrocode}
+\msg_new:nnnn { color } { CIELAB-requires-illuminant }
+  { CIELAB~color~space~'#1'~require~an~illuminant. }
+  {
+    LaTeX~has~been~asked~to~create~a~separation~color~space~using~
+    CIELAB~specifications,~but~no~\\ \\
+    \iow_indent:n { illuminant~=~<basis> }
+    \\ \\
+    key~was~given~with~the~correct~information.~LaTeX~will~use~illuminant~
+    'd50'~for~recovery.
+  }
+\msg_new:nnnn { color } { conversion-not-available }
+  { No~model~conversion~available~from~'#1'~to~'#2'. }
+  {
+    LaTeX~has~been~asked~to~convert~a~color~from~model~'#1'~
+    to~model'#2',~but~there~is~no~method~available~to~do~that.
+  }
+\msg_new:nnnn { color } { DeviceN-inconsistent-alternative }
+  { DeviceN~color~spaces~require~a~single~alternative~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space~'#1',~
+    but~the~constituent~colors~do~not~have~a~common~alternative~
+    color.
+  }
+\msg_new:nnnn { color } { DeviceN-no-alternative }
+  { DeviceN~color~spaces~require~an~alternative~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space~'#1',~
+    but~the~constituent~colors~do~not~all~have~a~device-based~alternative.
+  }
+\msg_new:nnnn { color } { DeviceN-requires-names }
+  { DeviceN~color~space~'#1'~require~a~list~of~names. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space,~
+    but~no~\\ \\
+    \iow_indent:n { names~=~<names> }
+    \\ \\
+    key~was~given~with~the~correct~information.
+  }
+\msg_new:nnnn { color } { ICC-Device-unknown }
+  { Unknown~device~color~space~'#1'. }
+  {
+    LaTeX~has~been~asked~to~apply~an~ICC~profile~but~the~device~color~space~
+    '#1'~is~unknown.
+  }
+\msg_new:nnnn { color } { ICCBased-unsupported-colorspace }
+  { ICCBased~color~space~'#1'~uses~an~unsupported~data~color~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~ICCBased~colorspace,~but~the~
+    used~data~colorspace~is~not~supported.~ICC~profiles~used~for~
+    defining~a~ICCBased~colorspace~should~use~a~Lab,~RGB,~or~
+    CMYK~data~colorspace.~LaTeX~will~ignore~this~request.
+  }
+\msg_new:nnnn { color } { ICCBased-requires-file }
+  { ICCBased~color~space~'#1'~require~an~file. }
+  {
+    LaTeX~has~been~asked~to~create~an~ICCBased~color~space,~but~no~\\ \\
+    \iow_indent:n { file~=~<name> }
+    \\ \\
+    key~was~given~with~the~correct~information.~LaTeX~will~ignore~this~
+    request.
+  }
+\msg_new:nnnn { color } { model-already-defined }
+  { Color~model~'#1'~already~defined. }
+  {
+    LaTeX~was~asked~to~define~a~new~color~model~called~'#1',~but~
+    this~color~model~already~exists.
+  }
+\msg_new:nnnn { color } { out-of-range }
+  { Input~value~#1~out~of~range~[#2,~#3]. }
+  {
+    LaTeX~was~expecting~a~value~in~the~range~[#2,~#3]~as~part~of~a~color,~
+    but~you~gave~#1.~LaTeX~will~assume~you~meant~the~limit~of~the~range~
+    and~continue.
+  }
+\msg_new:nnnn { color } { separation-alternative-model }
+  { Separation~color~space~'#1'~require~an~alternative~model. }
+  {
+    LaTeX~has~been~asked~to~create~a~separation~color~space,~
+    but~no~\\ \\
+    \iow_indent:n { alternative-model~=~<model> }
+    \\ \\
+    key~was~given~with~the~correct~information.
+  }
+\msg_new:nnnn { color } { separation-alternative-values }
+  { Separation~color~space~'#1'~require~values~for~the~alternative~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~separation~color~space,~
+    but~no~\\ \\
+    \iow_indent:n { alternative-values~=~<model> }
+    \\ \\
+    key~was~given~with~the~correct~information.
+  }
+\msg_new:nnnn { color } { separation-requires-name }
+  { Separation~color~space~'#1'~require~a~formal~name. }
+  {
+    LaTeX~has~been~asked~to~create~a~separation~color~space,~
+    but~no~\\ \\
+    \iow_indent:n { name~=~<formal~name> }
+    \\ \\
+    key~was~given~with~the~correct~information.
+  }
+\msg_new:nnn { color } { unhandled-model }
+  {
+    Unhandled~color~model~in~LaTeX2e~value~"#1":
+    \\ \\
+    falling~back~on~grayscale.
+  }
+\msg_new:nnnn { color } { unknown-color }
+  { Unknown~color~'#1'. }
+  {
+    LaTeX~has~been~asked~to~use~a~color~named~'#1',~
+    but~this~has~never~been~defined.
+  }
+\msg_new:nnnn { color } { unknown-alternative-model }
+  { Separation~color~space~'#1'~require~an~valid~alternative~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~separation~color~space,~
+    but~the~model~given~as\\ \\
+    \iow_indent:n { alternative-model~=~<model> }
+    \\ \\
+    is~unknown.
+  }
+\msg_new:nnnn { color } { unknown-export-format }
+  { Unknown~export~format~'#1'. }
+  {
+    LaTeX~has~been~asked~to~export~a~color~in~format~'#1',~
+    but~this~has~never~been~defined.
+  }
+\msg_new:nnnn { color } { unknown-CIELAB-illuminant }
+  { Unknown~illuminant~model~'#1'. }
+  {
+    LaTeX~has~been~asked~to~use~create~a~color~space~using~CIELAB~
+    illuminant~'#1',~but~this~does~not~exist.
+  }
+\msg_new:nnnn { color } { unknown-model }
+  { Unknown~color~model~'#1'. }
+  {
+    LaTeX~has~been~asked~to~use~a~color~model~called~'#1',~
+    but~this~model~is~not~set~up.
+  }
+\msg_new:nnnn { color } { unknown-model-type }
+  { Unknown~color~model~type~'#1'. }
+  {
+    LaTeX~has~been~asked~to~create~a~new~color~model~called~'#1',~
+    but~this~type~of~model~was~never~set~up.
+  }
+\prop_gput:Nnn \g_msg_module_name_prop { color } { LaTeX }
+\prop_gput:Nnn \g_msg_module_type_prop { color } { }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\msg_new:nnn { color } { show }
+  {
+    The~color~#1~
+    \tl_if_empty:nTF {#2}
+      { is~undefined. }
+      { has~the~properties: #2 }
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3color.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3debug.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3debug.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3debug.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,1478 @@
+% \iffalse meta-comment
+%
+%% File: l3debug.dtx
+%
+% Copyright (C) 2019-2024 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 \pkg{l3debug} module\\ Debugging support^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3debug} implementation}
+%
+% Internal kernel functions that are only defined here are listed in
+% \pkg{l3kernel-functions},
+% see~\ref{sec:l3kernel-functions:l3debug-internals}.
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=debug>
+%    \end{macrocode}
+%
+% Standard file identification.
+%    \begin{macrocode}
+\ProvidesExplFile{l3debug.def}{2024-04-11}{}{L3 Debugging support}
+%    \end{macrocode}
+%
+% \begin{variable}{\s_@@_stop}
+%   Internal scan marks.
+%    \begin{macrocode}
+\scan_new:N \s_@@_stop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[EXP]{\@@_use_i_delimit_by_s_stop:nw}
+%   Functions to gobble up to a scan mark.
+%    \begin{macrocode}
+\cs_new:Npn \@@_use_i_delimit_by_s_stop:nw #1 #2 \s_@@_stop {#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\q_@@_recursion_tail,\q_@@_recursion_stop}
+%   Internal quarks.
+%    \begin{macrocode}
+\quark_new:N \q_@@_recursion_tail
+\quark_new:N \q_@@_recursion_stop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[EXP]{\@@_if_recursion_tail_stop:N}
+%   Functions to query recursion quarks.
+%    \begin{macrocode}
+\cs_new:Npn \@@_use_none_delimit_by_q_recursion_stop:w
+  #1 \q_@@_recursion_stop { }
+\__kernel_quark_new_test:N \@@_if_recursion_tail_stop:N
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\debug_on:n, \debug_off:n, \@@_all_on:, \@@_all_off:}
+%    \begin{macrocode}
+\cs_gset_protected:Npn \debug_on:n #1
+  {
+    \exp_args:No \clist_map_inline:nn { \tl_to_str:n {#1} }
+      {
+        \cs_if_exist_use:cF { @@_ ##1 _on: }
+          { \msg_error:nnn { debug } { debug } {##1} }
+      }
+  }
+\cs_gset_protected:Npn \debug_off:n #1
+  {
+    \exp_args:No \clist_map_inline:nn { \tl_to_str:n {#1} }
+      {
+        \cs_if_exist_use:cF { @@_ ##1 _off: }
+          { \msg_error:nnn { debug } { debug } {##1} }
+      }
+  }
+\cs_new_protected:Npn \@@_all_on:
+  {
+    \debug_on:n
+      {
+        check-declarations ,
+        check-expressions ,
+        deprecation ,
+        log-functions ,
+      }
+  }
+\cs_new_protected:Npn \@@_all_off:
+  {
+    \debug_off:n
+      {
+        check-declarations ,
+        check-expressions ,
+        deprecation ,
+        log-functions ,
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\debug_suspend:, \debug_resume:}
+% \begin{macro}{\@@_suspended:T}
+% \begin{macro}{\l_@@_suspended_tl}
+%   Suspend and resume locally all debug-related errors and logging
+%   except deprecation errors.  The \cs{debug_suspend:} and \cs{debug_resume:}
+%   pairs can be nested.  We keep track of nesting in a token list
+%   containing a number of periods.  At first begin with the
+%   \enquote{non-suspended} version of \cs{@@_suspended:T}.
+%    \begin{macrocode}
+\tl_new:N \l_@@_suspended_tl { }
+\cs_gset_protected:Npn \debug_suspend:
+  {
+    \tl_put_right:Nn \l_@@_suspended_tl { . }
+    \cs_set_eq:NN \@@_suspended:T \use:n
+  }
+\cs_gset_protected:Npn \debug_resume:
+  {
+    \__kernel_tl_set:Nx \l_@@_suspended_tl
+      { \tl_tail:N \l_@@_suspended_tl }
+    \tl_if_empty:NT \l_@@_suspended_tl
+      {
+        \cs_set_eq:NN \@@_suspended:T \use_none:n
+      }
+  }
+\cs_new_eq:NN \@@_suspended:T \use_none:n
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {\@@_check-declarations_on:, \@@_check-declarations_off:}
+% \begin{macro}
+%   {
+%     \__kernel_chk_var_exist:N,
+%     \__kernel_chk_cs_exist:N,
+%     \__kernel_chk_cs_exist:c
+%   }
+% \begin{macro}[EXP]{\__kernel_chk_flag_exist:NN}
+% \begin{macro}{\__kernel_chk_var_local:N, \__kernel_chk_var_global:N}
+% \begin{macro}{\__kernel_chk_var_scope:NN}
+%   When debugging is enabled these two functions set up functions that
+%   test their argument (when \texttt{check-declarations} is active)
+%   \begin{itemize}
+%     \item \cs{__kernel_chk_var_exist:N} and \cs{__kernel_chk_cs_exist:N}, two
+%       functions that test that their argument is defined;
+%     \item \cs{__kernel_chk_var_scope:NN} that checks that its argument |#2|
+%       has scope |#1|.
+%     \item \cs{__kernel_chk_var_local:N} and \cs{__kernel_chk_var_global:N} that
+%       perform both checks.
+%   \end{itemize}
+%    \begin{macrocode}
+\cs_new_protected:Npn \__kernel_chk_var_exist:N #1 { }
+\cs_new_protected:Npn \__kernel_chk_cs_exist:N #1 { }
+\cs_generate_variant:Nn \__kernel_chk_cs_exist:N { c }
+\cs_new:Npn \__kernel_chk_flag_exist:NN { }
+\cs_new_protected:Npn \__kernel_chk_var_local:N #1 { }
+\cs_new_protected:Npn \__kernel_chk_var_global:N #1 { }
+\cs_new_protected:Npn \__kernel_chk_var_scope:NN #1#2 { }
+\cs_new_protected:cpn { @@_check-declarations_on: }
+  {
+    \cs_set_protected:Npn \__kernel_chk_var_exist:N ##1
+      {
+        \@@_suspended:T \use_none:nnn
+        \cs_if_exist:NF ##1
+          {
+            \msg_error:nne { debug } { non-declared-variable }
+              { \token_to_str:N ##1 }
+          }
+      }
+    \cs_set_protected:Npn \__kernel_chk_cs_exist:N ##1
+      {
+        \@@_suspended:T \use_none:nnn
+        \cs_if_exist:NF ##1
+          {
+            \msg_error:nne { kernel } { command-not-defined }
+              { \token_to_str:N ##1 }
+          }
+      }
+    \cs_set:Npn \__kernel_chk_flag_exist:NN ##1##2
+      {
+        \@@_suspended:T \use_iii:nnnn
+        \flag_if_exist:NTF ##2
+          { ##1 ##2 }
+          {
+            \msg_expandable_error:nnn { kernel } { bad-variable } {##2}
+            ##1 \l_tmpa_flag
+          }
+      }
+    \cs_set_protected:Npn \__kernel_chk_var_scope:NN
+      {
+        \@@_suspended:T \use_none:nnn
+        \@@_chk_var_scope_aux:NN
+      }
+    \cs_set_protected:Npn \__kernel_chk_var_local:N ##1
+      {
+        \@@_suspended:T \use_none:nnnnn
+        \__kernel_chk_var_exist:N ##1
+        \@@_chk_var_scope_aux:NN l ##1
+      }
+    \cs_set_protected:Npn \__kernel_chk_var_global:N ##1
+      {
+        \@@_suspended:T \use_none:nnnnn
+        \__kernel_chk_var_exist:N ##1
+        \@@_chk_var_scope_aux:NN g ##1
+      }
+  }
+\cs_new_protected:cpn { @@_check-declarations_off: }
+  {
+    \cs_set_protected:Npn \__kernel_chk_var_exist:N ##1 { }
+    \cs_set_protected:Npn \__kernel_chk_cs_exist:N ##1 { }
+    \cs_set:Npn \__kernel_chk_flag_exist:NN { }
+    \cs_set_protected:Npn \__kernel_chk_var_local:N ##1 { }
+    \cs_set_protected:Npn \__kernel_chk_var_global:N ##1 { }
+    \cs_set_protected:Npn \__kernel_chk_var_scope:NN ##1##2 { }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_chk_var_scope_aux:NN}
+% \begin{macro}{\@@_chk_var_scope_aux:Nn}
+% \begin{macro}{\@@_chk_var_scope_aux:NNn}
+%   First check whether the name of the variable |#2| starts with
+%   \meta{letter}|_|.  If it does then pass that letter, the
+%   \meta{scope}, and the variable name to
+%   \cs{@@_chk_var_scope_aux:NNn}.  That function compares the two
+%   letters and triggers an error if they differ (the \cs{scan_stop:}
+%   case is not reachable here).  If the second character was not |_|
+%   then pass the same data to the same auxiliary, except for its first
+%   argument which is now a control sequence.  That control sequence is
+%   actually a token list (but to avoid triggering the checking code we
+%   manipulate it using \cs{cs_set_nopar:Npn}) containing a single
+%   letter \meta{scope} according to what the first assignment to the
+%   given variable was.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_chk_var_scope_aux:NN #1#2
+  { \exp_args:NNf \@@_chk_var_scope_aux:Nn #1 { \cs_to_str:N #2 } }
+\cs_new_protected:Npn \@@_chk_var_scope_aux:Nn #1#2
+  {
+    \if:w _ \use_i:nn \@@_use_i_delimit_by_s_stop:nw #2 ? ? \s_@@_stop
+      \exp_after:wN \@@_chk_var_scope_aux:NNn
+        \@@_use_i_delimit_by_s_stop:nw #2 ? \s_@@_stop
+        #1 {#2}
+    \else:
+      \exp_args:Nc \@@_chk_var_scope_aux:NNn
+        { @@_chk_/ #2 }
+        #1 {#2}
+    \fi:
+  }
+\cs_new_protected:Npn \@@_chk_var_scope_aux:NNn #1#2#3
+  {
+    \if:w #1 #2
+    \else:
+      \if:w #1 \scan_stop:
+        \cs_gset_nopar:Npn #1 {#2}
+      \else:
+        \msg_error:nneee { debug } { local-global }
+          {#1} {#2} { \iow_char:N \\ #3 }
+      \fi:
+    \fi:
+  }
+\use:c { @@_check-declarations_off: }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_log-functions_on:, \@@_log-functions_off:}
+% \begin{macro}{\__kernel_debug_log:e}
+%   These two functions (corresponding to the \pkg{expl3} option
+%   \texttt{log-functions}) control whether \cs{__kernel_debug_log:e}
+%   writes to the log file or not.  By default, logging is off.
+%    \begin{macrocode}
+\cs_new_protected:cpn { @@_log-functions_on: }
+  {
+    \cs_set_protected:Npn \__kernel_debug_log:e
+      { \@@_suspended:T \use_none:nn \iow_log:e }
+  }
+\cs_new_protected:cpn { @@_log-functions_off: }
+  { \cs_set_protected:Npn \__kernel_debug_log:e { \use_none:n } }
+\cs_new_protected:Npn \__kernel_debug_log:e { \use_none:n }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {\@@_check-expressions_on:, \@@_check-expressions_off:}
+% \begin{macro}{\__kernel_chk_expr:nNnN}
+% \begin{macro}{\@@_chk_expr_aux:nNnN}
+%   When debugging is enabled these two functions set
+%   \cs{__kernel_chk_expr:nNnN} to test or not whether the given
+%   expression is valid.  The idea is to evaluate the expression within
+%   a brace group (to catch trailing \cs{use_none:nn} or similar), then
+%   test that the result is what we expect.  This is done by turning it
+%   to an integer and hitting that with \cs{tex_romannumeral:D} after
+%   replacing the first character by |-0|.  If all goes well, that
+%   primitive finds a non-positive integer and gives an empty output.
+%   If the original expression evaluation stopped early it leaves a
+%   trailing \cs{tex_relax:D}, which stops the second evaluation (used
+%   to convert to integer) before it encounters the final
+%   \cs{tex_relax:D}.  Since \cs{tex_romannumeral:D} does not absorb
+%   \cs{tex_relax:D} the output will be nonempty.  Note that |#3| is
+%   empty except for mu expressions for which it is \cs{tex_mutoglue:D}
+%   to avoid an \enquote{incompatible glue units} error.  Note also that
+%   if we had omitted the first \cs{tex_relax:D} then for instance
+%   |1+2\relax+3| would incorrectly be accepted as a valid integer
+%   expression.
+%    \begin{macrocode}
+\cs_new_protected:cpn { @@_check-expressions_on: }
+  {
+    \cs_set:Npn \__kernel_chk_expr:nNnN ##1##2
+      {
+        \@@_suspended:T { ##1 \use_none:nnnnnnn }
+        \exp_after:wN \@@_chk_expr_aux:nNnN
+        \exp_after:wN { \tex_the:D ##2 ##1 \scan_stop: }
+        ##2
+      }
+  }
+\cs_new_protected:cpn { @@_check-expressions_off: }
+  { \cs_set:Npn \__kernel_chk_expr:nNnN ##1##2##3##4 {##1} }
+\cs_new:Npn \__kernel_chk_expr:nNnN #1#2#3#4 {#1}
+\cs_new:Npn \@@_chk_expr_aux:nNnN #1#2#3#4
+  {
+    \tl_if_empty:oF
+      {
+        \tex_romannumeral:D - 0
+        \exp_after:wN \use_none:n
+        \int_value:w #3 #2 #1 \scan_stop:
+      }
+      {
+        \msg_expandable_error:nnnn
+          { debug } { expr } {#4} {#1}
+      }
+    #1
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_deprecation_on:, \@@_deprecation_off:}
+%   Make deprecated commands throw errors if the user requests it.
+%   This relies on two token lists, filled up in \pkg{l3deprecation} by
+%   calls to \cs{__kernel_deprecation_code:nn}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_deprecation_on:
+  { \g_@@_deprecation_on_tl }
+\cs_new_protected:Npn \@@_deprecation_off:
+  { \g_@@_deprecation_off_tl }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{
+%     \l_@@_internal_tl,
+%     \l_@@_tmpa_tl,
+%     \l_@@_tmpb_tl,
+%   }
+%   For patching.
+%    \begin{macrocode}
+\tl_new:N \l_@@_internal_tl
+\tl_new:N \l_@@_tmpa_tl
+\tl_new:N \l_@@_tmpb_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{
+%     \@@_generate_parameter_list:NNN,
+%     \@@_build_parm_text:n,
+%     \@@_build_arg_list:n,
+%     \@@_arg_list_from_signature:nNN,
+%     \@@_arg_check_invalid:N,
+%     \@@_parm_terminate:w,
+%     \@@_arg_if_braced:n,
+%     \@@_get_base_form:N,
+%     \@@_arg_return:N,
+%   }
+% \begin{macro}[TF]{\@@_arg_if_braced:N}
+%   Some functions don't take the arguments their signature indicates.
+%   For instance, \cs{clist_concat:NNN} doesn't take (directly) any
+%   argument, so patching it with something that uses |#1|, |#2|, or
+%   |#3| results in ``Illegal parameter number in definition of
+%   \cs{clist_concat:NNN}''.
+%
+%   Instead of changing \emph{the} definition of the macros, we'll
+%   create a copy of such macros, say, \cs[no-index]{@@_clist_concat:NNN} which
+%   will be defined as
+%   |<debug code with #1, #2 and #3>\clist_concat:NNN#1#2#3|. For that
+%   we need to identify the signature of every function and build the
+%   appropriate parameter list.
+%
+%   \cs{@@_generate_parameter_list:NNN} takes a function in |#1| and
+%   returns teo parameter lists: |#2| contains the simple |#1#2#3| as
+%   would be used in the \meta{parameter~text} of the definition and
+%   |#3| contains the same parameters but with braces where necessary.
+%
+%   With the current implementation the resulting |#3| is, for example
+%   for |\some_function:NnNn|, |#1{#2}#3{#4}|. While this is correct,
+%   it might be unnecessary. Bracing everything will usually have the
+%   same outcome (unless the function was misused in the first place).
+%   What should be done?
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_generate_parameter_list:NNN #1#2#3
+  {
+    \__kernel_tl_set:Nx \l_@@_internal_tl
+      { \exp_last_unbraced:Nf \use_ii:nnn \cs_split_function:N #1 }
+    \__kernel_tl_set:Nx #2
+      { \exp_args:NV \@@_build_parm_text:n \l_@@_internal_tl }
+    \__kernel_tl_set:Nx #3
+      { \exp_args:NV \@@_build_arg_list:n \l_@@_internal_tl }
+  }
+\cs_new:Npn \@@_build_parm_text:n #1
+  {
+    \@@_arg_list_from_signature:nNN { 1 } \c_false_bool #1
+    \q_@@_recursion_tail \q_@@_recursion_stop
+  }
+\cs_new:Npn \@@_build_arg_list:n #1
+  {
+    \@@_arg_list_from_signature:nNN { 1 } \c_true_bool #1
+    \q_@@_recursion_tail \q_@@_recursion_stop
+  }
+\cs_new:Npn \@@_arg_list_from_signature:nNN #1 #2 #3
+  {
+    \@@_if_recursion_tail_stop:N #3
+    \@@_arg_check_invalid:N #3
+    \bool_if:NT #2 { \@@_arg_if_braced:NT #3 { \use_none:n } }
+    \use:n { \c_hash_str \int_eval:n {#1} }
+    \exp_args:Nf \@@_arg_list_from_signature:nNN
+      { \int_eval:n {#1+1} } #2
+  }
+%    \end{macrocode}
+%   Argument types |w|, |p|, |T|, and |F| shouldn't be included in the
+%   parameter lists, so we abort the loop if either is found.
+%    \begin{macrocode}
+\cs_new:Npn \@@_arg_check_invalid:N #1
+  {
+    \if:w w #1 \@@_parm_terminate:w \else:
+      \if:w p #1 \@@_parm_terminate:w \else:
+        \if:w T #1 \@@_parm_terminate:w \else:
+          \if:w F #1 \@@_parm_terminate:w \else:
+            \exp:w
+          \fi:
+        \fi:
+      \fi:
+    \fi:
+    \exp_end:
+  }
+\cs_new:Npn \@@_parm_terminate:w
+  { \exp_after:wN \@@_use_none_delimit_by_q_recursion_stop:w \exp:w }
+\prg_new_conditional:Npnn \@@_arg_if_braced:N #1 { T }
+  { \exp_args:Nf \@@_arg_if_braced:n { \@@_get_base_form:N #1 } }
+\cs_new:Npn \@@_arg_if_braced:n #1
+  {
+    \if:w n #1 \prg_return_true: \else:
+      \if:w N #1 \prg_return_false: \else:
+        \msg_expandable_error:nnn
+          { debug } { bad-arg-type } {#1}
+      \fi:
+    \fi:
+  }
+\msg_new:nnn { debug } { bad-arg-type }
+  { Wrong~argument~type~#1. }
+%    \end{macrocode}
+%   The macro below gets the base form of an
+%   argument type given a variant. It serves only to differentiate
+%   arguments which should be braced from ones which shouldn't. If all
+%   were to be braced this would be unnecessary. I moved the |n| and |N|
+%   variants to the beginning of the test as the are much more common
+%   here.
+%    \begin{macrocode}
+\cs_new:Npn \@@_get_base_form:N #1
+  {
+    \if:w n #1 \@@_arg_return:N n \else:
+      \if:w N #1 \@@_arg_return:N N \else:
+        \if:w c #1 \@@_arg_return:N N \else:
+          \if:w o #1 \@@_arg_return:N n \else:
+            \if:w V #1 \@@_arg_return:N n \else:
+              \if:w v #1 \@@_arg_return:N n \else:
+                \if:w f #1 \@@_arg_return:N n \else:
+                  \if:w e #1 \@@_arg_return:N n \else:
+                    \if:w x #1 \@@_arg_return:N n \else:
+                      \@@_arg_return:N \scan_stop:
+                    \fi:
+                  \fi:
+                \fi:
+              \fi:
+            \fi:
+          \fi:
+        \fi:
+      \fi:
+    \fi:
+    \exp_stop_f:
+  }
+\cs_new:Npn \@@_arg_return:N #1
+  { \exp_after:wN #1 \exp:w \exp_end_continue_f:w }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{
+%     \__kernel_patch:nnn,
+%     \__kernel_patch_aux:nnn,
+%     \@@_setup_debug_code:Nnn,
+%     \@@_add_to_debug_code:Nnn,
+%     \@@_insert_debug_code:Nnn,
+%     \__kernel_patch_weird:nnn,
+%     \__kernel_patch_weird_aux:nnn,
+%     \@@_patch_weird:Nnn,
+%   }
+%   Simple patching by adding material at the start and end of (a
+%   collection of) functions is straight-forward as we know the catcode
+%   set up. The approach is essentially that in \pkg{etoolbox}. Notice
+%   the need to worry about spaces: those are otherwise lost as normally
+%   in \pkg{expl3} code they would be~|~|.
+%
+%   As discussed above, some functions don't take arguments, so we can't
+%   patch something that uses an argument in them. For these functions
+%   \cs{__kernel_patch:nnn} is used. It starts by creating a copy of the
+%   function (say, \cs{clist_concat:NNN}) with a |__debug_| prefix in
+%   the name. This copy won't be changed. The code redefines the
+%   original function to take the exact same arguments as advertised in
+%   its signature (see \cs{@@_generate_parameter_list:NNN} above).
+%   The redefined function also contains the debug code in the proper
+%   position. If a function with the same name and the |__debug_| prefix
+%   was already defined, then the macro patches that definition by
+%   adding more debug code to it.
+%    \begin{macrocode}
+\group_begin:
+  \cs_set_protected:Npn \__kernel_patch:nnn
+    {
+      \group_begin:
+        \char_set_catcode_other:N \#
+        \__kernel_patch_aux:nnn
+    }
+  \cs_set_protected:Npn \__kernel_patch_aux:nnn #1#2#3
+    {
+        \char_set_catcode_parameter:N \#
+        \char_set_catcode_space:N \ %
+        \tex_endlinechar:D -1 \scan_stop:
+        \tl_map_inline:nn {#3}
+          {
+            \cs_if_exist:cTF { @@_ \cs_to_str:N ##1 }
+              { \@@_add_to_debug_code:Nnn }
+              { \@@_setup_debug_code:Nnn }
+                ##1 {#1} {#2}
+          }
+      \group_end:
+    }
+  \cs_set_protected:Npn \@@_setup_debug_code:Nnn #1#2#3
+    {
+      \cs_gset_eq:cN { @@_ \cs_to_str:N #1 } #1
+      \@@_generate_parameter_list:NNN #1 \l_@@_tmpa_tl \l_@@_tmpb_tl
+      \exp_args:Ne \tex_scantokens:D
+        {
+          \tex_global:D \cs_prefix_spec:N #1
+          \tex_def:D \exp_not:N #1
+          \tl_use:N \l_@@_tmpa_tl
+            {
+              \tl_to_str:n {#2}
+              \exp_not:c { @@_ \cs_to_str:N #1 }
+              \tl_use:N \l_@@_tmpb_tl
+              \tl_to_str:n {#3}
+            }
+        }
+    }
+  \cs_set_protected:Npn \@@_add_to_debug_code:Nnn #1#2#3
+    {
+      \use:e
+        {
+          \cs_set:Npn \exp_not:N \@@_tmp:w
+            ##1 \tl_to_str:n { macro: }
+            ##2 \tl_to_str:n { -> }
+            ##3 \c_backslash_str \tl_to_str:n { @@_ }
+                    \cs_to_str:N #1
+            ##4 \s_@@_stop
+            {
+              \exp_not:N \exp_args:Ne \exp_not:N \tex_scantokens:D
+                {
+                  \tex_global:D ##1
+                  \tex_def:D \exp_not:N #1 ##2
+                    {
+                      ##3 \tl_to_str:n {#2}
+                      \c_backslash_str @@_ \cs_to_str:N #1
+                      ##4 \tl_to_str:n {#3}
+                    }
+                }
+            }
+        }
+      \exp_after:wN \@@_tmp:w \cs_meaning:N #1 \s_@@_stop
+    }
+%    \end{macrocode}
+%   Some functions, however, won't work with the signature reading setup
+%   above because their signature contains |w|eird arguments. These
+%   functions need to be patched using \cs{__kernel_patch_weird:nnn},
+%   which won't make a copy of the function, rather it will patch the
+%   debug code directly into it. This means that whatever argument the
+%   debug code uses must be actually used by the patched function.
+%    \begin{macrocode}
+  \cs_set_protected:Npn \__kernel_patch_weird:nnn
+    {
+      \group_begin:
+        \char_set_catcode_other:N \#
+        \__kernel_patch_weird_aux:nnn
+    }
+  \cs_set_protected:Npn \__kernel_patch_weird_aux:nnn #1#2#3
+    {
+        \char_set_catcode_parameter:N \#
+        \char_set_catcode_space:N \ %
+        \tex_endlinechar:D -1 \scan_stop:
+        \tl_map_inline:nn {#3}
+          { \@@_patch_weird:Nnn ##1 {#1} {#2} }
+      \group_end:
+    }
+  \cs_set_protected:Npn \@@_patch_weird:Nnn #1#2#3
+    {
+      \use:e
+        {
+          \tex_endlinechar:D -1 \scan_stop:
+          \exp_not:N \tex_scantokens:D
+            {
+              \tex_global:D \cs_prefix_spec:N #1
+              \tex_def:D \exp_not:N #1
+              \cs_parameter_spec:N #1
+                {
+                  \tl_to_str:n {#2}
+                  \cs_replacement_spec:N #1
+                  \tl_to_str:n {#3}
+                }
+            }
+        }
+    }
+%    \end{macrocode}
+% \end{macro}
+%
+% Patching the second argument to ensure it exists. This happens before
+% we alter |#1| so the ordering is correct.  For many variable types
+% such as \texttt{int} a low-level error occurs when |#2| is unknown, so
+% adding a check is not needed.
+%    \begin{macrocode}
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_exist:N #2 }
+    { }
+    {
+      \bool_set_eq:NN
+      \bool_gset_eq:NN
+      \clist_set_eq:NN
+      \clist_gset_eq:NN
+      \fp_set_eq:NN
+      \fp_gset_eq:NN
+      \prop_set_eq:NN
+      \prop_gset_eq:NN
+      \seq_set_eq:NN
+      \seq_gset_eq:NN
+      \str_set_eq:NN
+      \str_gset_eq:NN
+      \tl_set_eq:NN
+      \tl_gset_eq:NN
+    }
+%    \end{macrocode}
+%
+% Patching both second and third arguments.
+%    \begin{macrocode}
+  \__kernel_patch:nnn
+    {
+      \__kernel_chk_var_exist:N #2
+      \__kernel_chk_var_exist:N #3
+    }
+    { }
+    {
+      \clist_concat:NNN
+      \clist_gconcat:NNN
+      \prop_concat:NNN
+      \prop_gconcat:NNN
+      \seq_concat:NNN
+      \seq_gconcat:NNN
+      \str_concat:NNN
+      \str_gconcat:NNN
+      \tl_concat:NNN
+      \tl_gconcat:NNN
+    }
+%    \end{macrocode}
+%
+%
+%    \begin{macrocode}
+\cs_gset_protected:Npn \__kernel_tl_set:Nx  { \cs_set_nopar:Npe }
+\cs_gset_protected:Npn \__kernel_tl_gset:Nx { \cs_gset_nopar:Npe }
+%    \end{macrocode}
+%
+% Patching where the first argument to a function needs scope-checking:
+% either local or global (so two lists).
+%    \begin{macrocode}
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_local:N #1 }
+    { }
+    {
+      \bool_set:Nn
+      \bool_set_eq:NN
+      \bool_set_true:N
+      \bool_set_false:N
+      \box_set_eq:NN
+      \box_set_eq_drop:NN
+      \box_set_to_last:N
+      \clist_clear:N
+      \clist_set_eq:NN
+      \dim_zero:N
+      \dim_set:Nn
+      \dim_set_eq:NN
+      \dim_add:Nn
+      \dim_sub:Nn
+      \fp_set_eq:NN
+      \int_zero:N
+      \int_set_eq:NN
+      \int_add:Nn
+      \int_sub:Nn
+      \int_incr:N
+      \int_decr:N
+      \int_set:Nn
+      \hbox_set:Nn
+      \hbox_set_to_wd:Nnn
+      \hbox_set:Nw
+      \hbox_set_to_wd:Nnw
+      \muskip_zero:N
+      \muskip_set:Nn
+      \muskip_add:Nn
+      \muskip_sub:Nn
+      \muskip_set_eq:NN
+      \prop_clear:N
+      \prop_concat:NNN
+      \prop_pop:NnN
+      \prop_pop:NnNT
+      \prop_pop:NnNF
+      \prop_pop:NnNTF
+      \prop_put:Nnn
+      \prop_put_if_not_in:Nnn
+      \prop_put_from_keyval:Nn
+      \prop_remove:Nn
+      \prop_set_eq:NN
+      \prop_set_from_keyval:Nn
+      \seq_set_eq:NN
+      \skip_zero:N
+      \skip_set:Nn
+      \skip_set_eq:NN
+      \skip_add:Nn
+      \skip_sub:Nn
+      \str_clear:N
+      \str_set_eq:NN
+      \str_put_left:Nn
+      \str_put_right:Nn
+      \__kernel_tl_set:Nx
+      \tl_clear:N
+      \tl_set_eq:NN
+      \tl_put_left:Nn
+      \tl_put_left:NV
+      \tl_put_left:Nv
+      \tl_put_left:Ne
+      \tl_put_left:No
+      \tl_put_right:Nn
+      \tl_put_right:NV
+      \tl_put_right:Nv
+      \tl_put_right:Ne
+      \tl_put_right:No
+      \tl_build_begin:N
+      \tl_build_put_right:Nn
+      \tl_build_put_left:Nn
+      \vbox_set:Nn
+      \vbox_set_top:Nn
+      \vbox_set_to_ht:Nnn
+      \vbox_set:Nw
+      \vbox_set_to_ht:Nnw
+      \vbox_set_split_to_ht:NNn
+    }
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_global:N #1 }
+    { }
+    {
+      \bool_gset:Nn
+      \bool_gset_eq:NN
+      \bool_gset_true:N
+      \bool_gset_false:N
+      \box_gset_eq:NN
+      \box_gset_eq_drop:NN
+      \box_gset_to_last:N
+      \cctab_gset:Nn
+      \clist_gclear:N
+      \clist_gset_eq:NN
+      \dim_gset_eq:NN
+      \dim_gzero:N
+      \dim_gset:Nn
+      \dim_gadd:Nn
+      \dim_gsub:Nn
+      \fp_gset_eq:NN
+      \int_gzero:N
+      \int_gset_eq:NN
+      \int_gadd:Nn
+      \int_gsub:Nn
+      \int_gincr:N
+      \int_gdecr:N
+      \int_gset:Nn
+      \hbox_gset:Nn
+      \hbox_gset_to_wd:Nnn
+      \hbox_gset:Nw
+      \hbox_gset_to_wd:Nnw
+      \muskip_gzero:N
+      \muskip_gset:Nn
+      \muskip_gadd:Nn
+      \muskip_gsub:Nn
+      \muskip_gset_eq:NN
+      \prop_gclear:N
+      \prop_gconcat:NNN
+      \prop_gpop:NnN
+      \prop_gpop:NnNT
+      \prop_gpop:NnNF
+      \prop_gpop:NnNTF
+      \prop_gput:Nnn
+      \prop_gput_if_not_in:Nnn
+      \prop_gput_from_keyval:Nn
+      \prop_gremove:Nn
+      \prop_gset_eq:NN
+      \prop_gset_from_keyval:Nn
+      \seq_gset_eq:NN
+      \skip_gzero:N
+      \skip_gset:Nn
+      \skip_gset_eq:NN
+      \skip_gadd:Nn
+      \skip_gsub:Nn
+      \str_gclear:N
+      \str_gset_eq:NN
+      \str_gput_left:Nn
+      \str_gput_right:Nn
+      \__kernel_tl_gset:Nx
+      \tl_gclear:N
+      \tl_gset_eq:NN
+      \tl_gput_left:Nn
+      \tl_gput_left:NV
+      \tl_gput_left:Nv
+      \tl_gput_left:Ne
+      \tl_gput_left:No
+      \tl_gput_right:Nn
+      \tl_gput_right:NV
+      \tl_gput_right:Nv
+      \tl_gput_right:Ne
+      \tl_gput_right:No
+      \tl_build_gbegin:N
+      \tl_build_gput_right:Nn
+      \tl_build_gput_left:Nn
+      \vbox_gset:Nn
+      \vbox_gset_top:Nn
+      \vbox_gset_to_ht:Nnn
+      \vbox_gset:Nw
+      \vbox_gset_to_ht:Nnw
+      \vbox_gset_split_to_ht:NNn
+    }
+%    \end{macrocode}
+%
+% Scoping for constants.
+%    \begin{macrocode}
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_scope:NN c #1 }
+    { }
+    {
+      \bool_const:Nn
+      \cctab_const:Nn
+      \dim_const:Nn
+      \int_const:Nn
+      \intarray_const_from_clist:Nn
+      \muskip_const:Nn
+      \prop_const_from_keyval:Nn
+      \prop_const_linked_from_keyval:Nn
+      \skip_const:Nn
+      \str_const:Nn
+      \tl_const:Nn
+    }
+%    \end{macrocode}
+%
+% Flag functions.
+%    \begin{macrocode}
+  \__kernel_patch:nnn
+    { \__kernel_chk_flag_exist:NN }
+    { }
+    {
+      \flag_ensure_raised:N
+      \flag_height:N
+      \flag_if_raised:NT
+      \flag_if_raised:NF
+      \flag_if_raised:NTF
+      \flag_if_raised_p:N
+      \flag_raise:N
+    }
+%    \end{macrocode}
+%
+% Various one-offs.
+%    \begin{macrocode}
+  \__kernel_patch:nnn
+    { \__kernel_chk_cs_exist:N #1 }
+    { }
+    { \cs_generate_variant:Nn }
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_scope:NN g #1 }
+    { }
+    { \cctab_new:N }
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_scope:NN l #1 }
+    { }
+    { \flag_new:N }
+  \__kernel_patch:nnn
+    {
+      \__kernel_chk_var_scope:NN l #1
+      \__kernel_chk_flag_exist:NN
+    }
+    { }
+    { \flag_clear:N }
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_scope:NN g #1 }
+    { }
+    { \intarray_new:Nn }
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_scope:NN q #1 }
+    { }
+    { \quark_new:N }
+  \__kernel_patch:nnn
+    { \__kernel_chk_var_scope:NN s #1 }
+    { }
+    { \scan_new:N }
+%    \end{macrocode}
+%
+% Patch various internal commands to log definitions of functions.
+% First, a kernel internal.  Then internals from the \pkg{cs},
+% \pkg{keys} and \pkg{msg} modules.
+%    \begin{macrocode}
+  \__kernel_patch:nnn
+    { }
+    {
+      \__kernel_debug_log:e
+        { Defining~\token_to_str:N #1~ \msg_line_context: }
+    }
+    { \__kernel_chk_if_free_cs:N }
+%<@@=cs>
+  \__kernel_patch_weird:nnn
+    {
+      \cs_if_free:NF #4
+        {
+          \__kernel_debug_log:e
+            {
+              Variant~\token_to_str:N #4~%
+              already~defined;~ not~ changing~ it~ \msg_line_context:
+            }
+        }
+    }
+    { }
+    { \@@_generate_variant:wwNN  }
+%<@@=keys>
+  \__kernel_patch:nnn
+    {
+      \cs_if_exist:cF { \c_@@_code_root_str #1 }
+        { \__kernel_debug_log:e { Defining~key~#1~\msg_line_context: } }
+    }
+    { }
+    { \@@_cmd_set_direct:nn }
+%<@@=msg>
+  \__kernel_patch:nnn
+    { }
+    {
+      \__kernel_debug_log:e
+        { Defining~message~ #1 / #2 ~\msg_line_context: }
+    }
+    { \@@_chk_free:nn }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=prg>
+%    \end{macrocode}
+% Internal functions from \pkg{prg} module.
+%    \begin{macrocode}
+  \__kernel_patch_weird:nnn
+    { \__kernel_chk_cs_exist:c { #5 _p : #6 } }
+    { }
+    { \@@_set_eq_conditional_p_form:wNnnnn }
+  \__kernel_patch_weird:nnn
+    { \__kernel_chk_cs_exist:c { #5    : #6 TF } }
+    { }
+    { \@@_set_eq_conditional_TF_form:wNnnnn }
+  \__kernel_patch_weird:nnn
+    { \__kernel_chk_cs_exist:c { #5    : #6 T } }
+    { }
+    { \@@_set_eq_conditional_T_form:wNnnnn }
+  \__kernel_patch_weird:nnn
+    { \__kernel_chk_cs_exist:c { #5    : #6 F } }
+    { }
+    { \@@_set_eq_conditional_F_form:wNnnnn }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=regex>
+%    \end{macrocode}
+% Internal functions from \pkg{regex} module.
+%    \begin{macrocode}
+  \__kernel_patch:nnn
+    {
+      \@@_trace_push:nnN { regex } { 1 } \@@_escape_use:nnnn
+      \group_begin:
+        \__kernel_tl_set:Nx \l_@@_internal_a_tl
+          { \@@_trace_pop:nnN { regex } { 1 } \@@_escape_use:nnnn }
+        \use_none:nnn
+    }
+    { }
+    { \@@_escape_use:nnn }
+  \__kernel_patch:nnn
+    { \@@_trace_push:nnN { regex } { 1 } \@@_build:N }
+    {
+      \@@_trace_states:n { 2 }
+      \@@_trace_pop:nnN { regex } { 1 } \@@_build:N
+    }
+    { \@@_build:N }
+  \__kernel_patch:nnn
+    { \@@_trace_push:nnN { regex } { 1 } \@@_build_for_cs:n }
+    {
+      \@@_trace_states:n { 2 }
+      \@@_trace_pop:nnN { regex } { 1 } \@@_build_for_cs:n
+    }
+    { \@@_build_for_cs:n }
+  \__kernel_patch:nnn
+    {
+      \@@_trace:nne { regex } { 2 }
+        {
+          regex~new~state~
+          L=\int_use:N \l_@@_left_state_int ~ -> ~
+          R=\int_use:N \l_@@_right_state_int ~ -> ~
+          M=\int_use:N \l_@@_max_state_int ~ -> ~
+          \int_eval:n { \l_@@_max_state_int + 1 }
+        }
+    }
+    { }
+    { \@@_build_new_state: }
+  \__kernel_patch:nnn
+    { \@@_trace_push:nnN { regex } { 1 } \@@_group_aux:nnnnN }
+    { \@@_trace_pop:nnN { regex } { 1 } \@@_group_aux:nnnnN }
+    { \@@_group_aux:nnnnN }
+  \__kernel_patch:nnn
+    { \@@_trace_push:nnN { regex } { 1 } \@@_branch:n }
+    { \@@_trace_pop:nnN { regex } { 1 } \@@_branch:n }
+    { \@@_branch:n }
+  \__kernel_patch:nnn
+    {
+      \@@_trace_push:nnN { regex } { 1 } \@@_match:n
+      \@@_trace:nne { regex } { 1 } { analyzing~query~token~list }
+    }
+    { \@@_trace_pop:nnN { regex } { 1 } \@@_match:n }
+    { \@@_match:n }
+  \__kernel_patch:nnn
+    {
+      \@@_trace_push:nnN { regex } { 1 } \@@_match_cs:n
+      \@@_trace:nne { regex } { 1 } { analyzing~query~token~list }
+    }
+    { \@@_trace_pop:nnN { regex } { 1 } \@@_match_cs:n }
+    { \@@_match_cs:n }
+  \__kernel_patch:nnn
+    { \@@_trace:nne { regex } { 1 } { initializing } }
+    { }
+    { \@@_match_init: }
+  \__kernel_patch:nnn
+    {
+      \@@_trace:nne { regex } { 2 }
+        { state~\int_use:N \l_@@_curr_state_int }
+    }
+    { }
+    { \@@_use_state: }
+  \__kernel_patch:nnn
+    { \@@_trace_push:nnN { regex } { 1 } \@@_replacement:n }
+    { \@@_trace_pop:nnN { regex } { 1 } \@@_replacement:n }
+    { \@@_replacement:n }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\group_end:
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=debug>
+%    \end{macrocode}
+%
+% Patching arguments is a bit more involved: we do these one at a time.
+% The basic idea is the same, using a |#| token that is a string.
+%    \begin{macrocode}
+\group_begin:
+  \cs_set_protected:Npn \__kernel_patch:Nn #1
+    {
+      \group_begin:
+        \char_set_catcode_other:N \#
+        \__kernel_patch_aux:Nn #1
+    }
+  \cs_set_protected:Npn \__kernel_patch_aux:Nn #1#2
+    {
+        \char_set_catcode_parameter:N \#
+        \tex_endlinechar:D -1 \scan_stop:
+        \exp_args:Ne \tex_scantokens:D
+          {
+            \tex_global:D \cs_prefix_spec:N #1 \tex_def:D \exp_not:N #1
+              \cs_parameter_spec:N #1
+              { \exp_args:No \tl_to_str:n { #1 #2 } }
+          }
+      \group_end:
+    }
+%    \end{macrocode}
+%
+% The functions here can get a bit repetitive, so we define a helper
+% which can re-use the same patch code repeatedly. The main part of the
+% patch is the same, so we just have to deal with the part which varies
+% depending on the type of expression.
+%    \begin{macrocode}
+  \cs_set_protected:Npn \__kernel_patch_eval:nn #1#2
+    {
+      \tl_map_inline:nn {#1}
+        {
+          \exp_args:NNe \__kernel_patch:Nn ##1
+            {
+              { \c_hash_str 1 }
+              {
+                \exp_not:N \__kernel_chk_expr:nNnN { \c_hash_str 2 }
+                \exp_not:n {#2}
+                \exp_not:N ##1
+              }
+            }
+        }
+    }
+%<@@=dim>
+  \__kernel_patch_eval:nn
+    {
+      \dim_set:Nn
+      \dim_gset:Nn
+      \dim_add:Nn
+      \dim_gadd:Nn
+      \dim_sub:Nn
+      \dim_gsub:Nn
+      \dim_const:Nn
+    }
+    { \@@_eval:w { } }
+%<@@=int>
+  \__kernel_patch_eval:nn
+    {
+      \int_set:Nn
+      \int_gset:Nn
+      \int_add:Nn
+      \int_gadd:Nn
+      \int_sub:Nn
+      \int_gsub:Nn
+      \int_const:Nn
+    }
+    { \@@_eval:w { } }
+  \__kernel_patch_eval:nn
+    {
+      \muskip_set:Nn
+      \muskip_gset:Nn
+      \muskip_add:Nn
+      \muskip_gadd:Nn
+      \muskip_sub:Nn
+      \muskip_gsub:Nn
+      \muskip_const:Nn
+    }
+    { \tex_muexpr:D { \tex_mutoglue:D } }
+  \__kernel_patch_eval:nn
+    {
+      \skip_set:Nn
+      \skip_gset:Nn
+      \skip_add:Nn
+      \skip_gadd:Nn
+      \skip_sub:Nn
+      \skip_gsub:Nn
+      \skip_const:Nn
+    }
+    { \tex_glueexpr:D { } }
+%    \end{macrocode}
+%
+% Patching expandable expressions, first the one-argument versions,
+% then the two-argument ones.
+%    \begin{macrocode}
+  \cs_set_protected:Npn \__kernel_patch_eval:nn #1#2
+    {
+      \tl_map_inline:nn {#1}
+        {
+          \exp_args:NNe \__kernel_patch:Nn ##1
+            {
+              {
+                \exp_not:N \__kernel_chk_expr:nNnN { \c_hash_str 1 }
+                \exp_not:n {#2}
+                \exp_not:N ##1
+              }
+            }
+        }
+    }
+%<@@=box>
+  \__kernel_patch_eval:nn
+    { \@@_dim_eval:n }
+    { \@@_dim_eval:w { } }
+%<@@=dim>
+  \__kernel_patch_eval:nn
+    {
+      \dim_eval:n
+      \dim_to_decimal:n
+      \dim_to_decimal_in_sp:n
+      \dim_abs:n
+      \dim_sign:n
+    }
+    { \@@_eval:w { } }
+%<@@=int>
+  \__kernel_patch_eval:nn
+    {
+      \int_eval:n
+      \int_abs:n
+      \int_sign:n
+    }
+    { \@@_eval:w { } }
+  \__kernel_patch_eval:nn
+    {
+      \skip_eval:n
+      \skip_horizontal:n
+      \skip_vertical:n
+    }
+    { \tex_glueexpr:D { } }
+  \__kernel_patch_eval:nn
+    {
+      \muskip_eval:n
+    }
+    { \tex_muexpr:D { \tex_mutoglue:D } }
+  \cs_set_protected:Npn \__kernel_patch_eval:nn #1#2
+    {
+      \tl_map_inline:nn {#1}
+        {
+          \exp_args:NNe \__kernel_patch:Nn ##1
+            {
+              {
+                \exp_not:N \__kernel_chk_expr:nNnN { \c_hash_str 1 }
+                \exp_not:n {#2}
+                \exp_not:N ##1
+              }
+              {
+                \exp_not:N \__kernel_chk_expr:nNnN { \c_hash_str 2 }
+                \exp_not:n {#2}
+                \exp_not:N ##1
+              }
+            }
+        }
+    }
+%<@@=dim>
+  \__kernel_patch_eval:nn
+    {
+      \dim_max:nn
+      \dim_min:nn
+    }
+    { \@@_eval:w { } }
+%<@@=int>
+  \__kernel_patch_eval:nn
+    {
+      \int_max:nn
+      \int_min:nn
+      \int_div_truncate:nn
+      \int_mod:nn
+    }
+    { \@@_eval:w { } }
+%    \end{macrocode}
+%
+%  Conditionals: three argument ones then one argument ones
+%    \begin{macrocode}
+  \cs_set_protected:Npn \__kernel_patch_cond:nn #1#2
+    {
+      \clist_map_inline:nn { :nNnT , :nNnF , :nNnTF , _p:nNn }
+        {
+          \exp_args:Nce \__kernel_patch:Nn { #1 ##1 }
+            {
+              {
+                \exp_not:N \__kernel_chk_expr:nNnN { \c_hash_str 1 }
+                \exp_not:n {#2}
+                \exp_not:c { #1 ##1 }
+              }
+              { \c_hash_str 2 }
+              {
+                \exp_not:N \__kernel_chk_expr:nNnN { \c_hash_str 3 }
+                \exp_not:n {#2}
+                \exp_not:c { #1 ##1 }
+              }
+            }
+        }
+    }
+%<@@=dim>
+  \__kernel_patch_cond:nn { dim_compare } { \@@_eval:w { } }
+%<@@=int>
+  \__kernel_patch_cond:nn { int_compare } { \@@_eval:w { } }
+  \cs_set_protected:Npn \__kernel_patch_cond:nn #1#2
+    {
+      \clist_map_inline:nn { :nT , :nF , :nTF , _p:n }
+        {
+          \exp_args:Nce \__kernel_patch:Nn { #1 ##1 }
+            {
+              {
+                \exp_not:N \__kernel_chk_expr:nNnN { \c_hash_str 1 }
+                \exp_not:n {#2}
+                \exp_not:c { #1 ##1 }
+              }
+            }
+        }
+    }
+%<@@=int>
+  \__kernel_patch_cond:nn { int_if_even } { \@@_eval:w { } }
+  \__kernel_patch_cond:nn { int_if_odd } { \@@_eval:w { } }
+%    \end{macrocode}
+%
+% Step functions.
+%    \begin{macrocode}
+%<@@=dim>
+  \__kernel_patch:Nn \dim_step_function:nnnN
+    {
+      {
+        \__kernel_chk_expr:nNnN {#1} \@@_eval:w { }
+          \dim_step_function:nnnN
+      }
+      {
+        \__kernel_chk_expr:nNnN {#2} \@@_eval:w { }
+          \dim_step_function:nnnN
+      }
+      {
+        \__kernel_chk_expr:nNnN {#3} \@@_eval:w { }
+          \dim_step_function:nnnN
+      }
+    }
+%<@@=int>
+  \__kernel_patch:Nn \int_step_function:nnnN
+    {
+      {
+        \__kernel_chk_expr:nNnN {#1} \@@_eval:w { }
+          \int_step_function:nnnN
+      }
+      {
+        \__kernel_chk_expr:nNnN {#2} \@@_eval:w { }
+          \int_step_function:nnnN
+      }
+      {
+        \__kernel_chk_expr:nNnN {#3} \@@_eval:w { }
+          \int_step_function:nnnN
+      }
+    }
+%    \end{macrocode}
+%
+%  Odds and ends
+%    \begin{macrocode}
+  \__kernel_patch:Nn \dim_to_fp:n { { (#1) } }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\group_end:
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=skip>
+%    \end{macrocode}
+% This one has catcode changes so must be done by hand.
+%    \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1
+  {
+    \prg_set_conditional:Npnn \skip_if_finite:n ##1 { p , T , F , TF }
+      {
+        \exp_after:wN \@@_if_finite:wwNw
+        \skip_use:N \tex_glueexpr:D
+          \__kernel_chk_expr:nNnN
+            {##1} \tex_glueexpr:D { } \skip_if_finite:n
+        ; \prg_return_false:
+        #1 ; \prg_return_true: \s_@@_stop
+      }
+  }
+\exp_args:No \@@_tmp:w { \tl_to_str:n { fil } }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=msg>
+%    \end{macrocode}
+%
+% Messages.
+% \begin{macrocode}
+\msg_new:nnnn { debug } { debug }
+  { The~debugging~option~'#1'~does~not~exist~\msg_line_context:. }
+  {
+    The~functions~'\iow_char:N\\debug_on:n'~and~
+    '\iow_char:N\\debug_off:n'~only~accept~the~arguments~
+    'all',~'check-declarations',~'check-expressions',~
+    'deprecation',~'log-functions',~not~'#1'.
+  }
+\msg_new:nnn { debug } { expr } { '#2'~in~#1 }
+\msg_new:nnnn { debug } { local-global }
+  { Inconsistent~local/global~assignment }
+  {
+    \c_@@_coding_error_text_tl
+    \if:w l #2 Local
+    \else:
+      \if:w g #2 Global \else: Constant \fi:
+    \fi:
+    \ %
+    assignment~to~a~
+    \if:w l #1 local
+    \else:
+      \if:w g #1 global \else: constant \fi:
+    \fi:
+    \ %
+    variable~'#3'.
+  }
+\msg_new:nnnn { debug } { non-declared-variable }
+  { The~variable~#1~has~not~been~declared~\msg_line_context:. }
+  {
+    \c_@@_coding_error_text_tl
+    Checking~is~active,~and~you~have~tried~do~so~something~like: \\
+    \ \ \tl_set:Nn ~ #1 ~ \{ ~ ... ~ \} \\
+    without~first~having: \\
+    \ \ \tl_new:N ~ #1  \\
+    \\
+    LaTeX~will~continue,~creating~the~variable~where~it~is~the~one~being~set.
+  }
+%    \end{macrocode}
+%
+% \begin{macro}{\__kernel_if_debug:TF}
+%   Flip the switch for deprecated code.
+%    \begin{macrocode}
+\cs_set_protected:Npn \__kernel_if_debug:TF #1#2 {#1}
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3debug.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3deprecation.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3deprecation.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3deprecation.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,691 @@
+% \iffalse meta-comment
+%
+%% File: l3deprecation.dtx
+%
+% Copyright (C) 2017-2024 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 \pkg{l3deprecation} module\\ Deprecation errors^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX{} Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released 2024-04-11}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \section{\pkg{l3deprecation} documentation}
+%
+% A few commands have had to be deprecated over the years.
+% All commands deprecated before release 2022-01-12 were already
+% removed; commands deprecated since then will no longer be removed.
+% Instead, this module defines them to produce errors.
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3deprecation} implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=deprecation>
+%    \end{macrocode}
+%
+% \subsection{Patching definitions to deprecate}
+%
+% \begin{quote}
+%   \cs{__kernel_patch_deprecation:nnNNpn} \Arg{date} \Arg{replacement}
+%   \meta{definition} \meta{function} \meta{parameters} \Arg{code}
+% \end{quote}
+% defines the \meta{function} to produce an error and run its
+% \meta{code}.
+%
+% We make \cs{debug_on:n} |{deprecation}| turn the \meta{function} into
+% an \tn{outer} error, and \cs{debug_off:n} |{deprecation}| restore
+% whatever the behaviour was without \cs{debug_on:n} |{deprecation}|.
+%
+% In the explanations below, \meta{definition} \meta{function}
+% \meta{parameters} \Arg{code} or assignments that only differ in the
+% scope of the \meta{definition} will be called \enquote{the standard
+% definition}.
+%
+% \begin{macro}
+%   {
+%     \__kernel_patch_deprecation:nnNNpn, \@@_patch_aux:nnNNnn,
+%     \@@_warn_once:nnNnn,
+%     \@@_patch_aux:Nn,
+%     \@@_just_error:nnNN
+%   }
+%   (The parameter text is grabbed using |#5#|.)  The arguments of
+%   \cs{__kernel_deprecation_code:nn} are run upon \cs{debug_on:n}
+%   |{deprecation}| and \cs{debug_off:n} |{deprecation}|, respectively.
+%   In both scenarios we the \meta{function} may be \tn{outer} so we
+%   undefine it with \cs{tex_let:D} before redefining it, with
+%   \cs{__kernel_deprecation_error:Nnn} or with some code added shortly.
+%    \begin{macrocode}
+\cs_new_protected:Npn \__kernel_patch_deprecation:nnNNpn #1#2#3#4#5#
+  { \@@_patch_aux:nnNNnn {#1} {#2} #3 #4 {#5} }
+\cs_new_protected:Npn \@@_patch_aux:nnNNnn #1#2#3#4#5#6
+  {
+    \__kernel_deprecation_code:nn
+      {
+        \tex_let:D #4 \scan_stop:
+        \__kernel_deprecation_error:Nnn #4 {#2} {#1}
+      }
+      { \tex_let:D #4 \scan_stop: }
+    \cs_if_eq:NNTF #3 \cs_gset_protected:Npn
+      { \@@_warn_once:nnNnn {#1} {#2} #4 {#5} {#6} }
+      { \@@_patch_aux:Nn #3 { #4 #5 {#6} } }
+  }
+%    \end{macrocode}
+%   In case we want a warning, the \meta{function} is defined to produce
+%   such a warning without grabbing any argument, then redefine itself
+%   to the standard definition that the \meta{function} should have,
+%   with arguments, and call that definition.  The \texttt{e}-type
+%   expansion and \cs{exp_not:n} avoid needing to double the~|#|, which
+%   we could not do anyways.  We then deal with the code for
+%   \cs{debug_off:n} |{deprecation}|: presumably someone doing that does
+%   not need the warning so we simply do the standard definition.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_warn_once:nnNnn #1#2#3#4#5
+  {
+    \cs_gset_protected:Npe #3
+      {
+        \__kernel_if_debug:TF
+          {
+            \exp_not:N \msg_warning:nneee
+              { deprecation } { deprecated-command }
+              {#1}
+              { \token_to_str:N #3 }
+              { \tl_to_str:n {#2} }
+          }
+          { }
+        \exp_not:n { \cs_gset_protected:Npn #3 #4 {#5} }
+        \exp_not:N #3
+      }
+    \__kernel_deprecation_code:nn { }
+      { \cs_set_protected:Npn #3 #4 {#5} }
+  }
+%    \end{macrocode}
+%   In case we want neither warning nor error, the \meta{function} is
+%   given its standard definition.  Here |#1| is \cs{cs_new:Npn} or
+%   \cs{cs_new_protected:Npn}) and |#2| is \meta{function}
+%   \meta{parameters} \Arg{code}, so |#1#2| performs the assignment.
+%   For \cs{debug_off:n} |{deprecation}| we want to use the same
+%   assignment but with a different scope, hence the \cs{cs_if_eq:NNTF}
+%   test.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_patch_aux:Nn #1#2
+  {
+    #1 #2
+    \cs_if_eq:NNTF #1 \cs_gset_protected:Npn
+      { \__kernel_deprecation_code:nn { } { \cs_set_protected:Npn #2 } }
+      { \__kernel_deprecation_code:nn { } { \cs_set:Npn #2 } }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\__kernel_deprecation_error:Nnn}
+%   The \tn{outer} definition here ensures the command cannot appear
+%   in an argument.
+%    \begin{macrocode}
+\cs_new_protected:Npn \__kernel_deprecation_error:Nnn #1#2#3
+  {
+    \tex_protected:D \tex_outer:D \tex_edef:D #1
+      {
+        \exp_not:N \msg_expandable_error:nnnnn
+          { deprecation } { deprecated-command }
+          { \tl_to_str:n {#3} } { \token_to_str:N #1 } { \tl_to_str:n {#2} }
+        \exp_not:N \msg_error:nneee
+          { deprecation } { deprecated-command }
+          { \tl_to_str:n {#3} } { \token_to_str:N #1 } { \tl_to_str:n {#2} }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+\msg_new:nnn { deprecation } { deprecated-command }
+  {
+    \tl_if_blank:nF {#3} { Use~ \tl_trim_spaces:n {#3} ~not~ }
+    #2~deprecated~on~#1.
+  }
+%    \end{macrocode}
+%
+% \subsection{Deprecated \pkg{l3basics} functions}
+%
+%    \begin{macrocode}
+%<@@=cs>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP, deprecated]{\cs_argument_spec:N}
+%   For the present, do not deprecate fully as \LaTeXe{} will need to catch
+%   up: one for Fall 2022.
+%    \begin{macrocode}
+%\__kernel_patch_deprecation:nnNNpn { 2022-06-24 } { \cs_parameter_spec:N }
+\cs_new:Npn \cs_argument_spec:N { \cs_parameter_spec:N }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3file} functions}
+%
+%    \begin{macrocode}
+%<@@=file>
+%    \end{macrocode}
+%
+% \begin{macro}[deprecated]
+%   {
+%     \iow_shipout_x:Nn, \iow_shipout_x:Nx,
+%     \iow_shipout_x:cn, \iow_shipout_x:cx
+%   }
+%   Previously described as \texttt{x}-type, but the hash behaviour is really
+%   \texttt{e}-type. Currently not \enquote{live} as we need to have a transition.
+%    \begin{macrocode}
+% \__kernel_patch_deprecation:nnNNpn { 2023-10-10 } { \iow_shipout_e:Nn }
+\cs_new_protected:Npn \iow_shipout_x:Nn { \iow_shipout_e:Nn }
+\cs_generate_variant:Nn \iow_shipout_x:Nn { Nx , c, cx }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3keys} functions}
+%
+%    \begin{macrocode}
+%<@@=keys>
+%    \end{macrocode}
+%
+% \begin{macro}[deprecated]{.str_set_x:N, .str_set_x:c}
+% \begin{macro}[deprecated]{.str_gset_x:N, .str_gset_x:c}
+%    \begin{macrocode}
+\cs_new_protected:cpn { \c_@@_props_root_str .str_set_x:N } #1
+  { \@@_variable_set:NnnN #1 { str } { } x }
+\cs_new_protected:cpn { \c_@@_props_root_str .str_set_x:c } #1
+  { \@@_variable_set:cnnN {#1} { str } { } x }
+\cs_new_protected:cpn { \c_@@_props_root_str .str_gset_x:N } #1
+  { \@@_variable_set:NnnN #1 { str } { g } x }
+\cs_new_protected:cpn { \c_@@_props_root_str .str_gset_x:c } #1
+  { \@@_variable_set:cnnN {#1} { str } { g } x }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[deprecated]{.tl_set_x:N, .tl_set_x:c}
+% \begin{macro}[deprecated]{.tl_gset_x:N, .tl_gset_x:c}
+%    \begin{macrocode}
+\cs_new_protected:cpn { \c_@@_props_root_str .tl_set_x:N } #1
+  { \@@_variable_set:NnnN #1 { tl } { } x }
+\cs_new_protected:cpn { \c_@@_props_root_str .tl_set_x:c } #1
+  { \@@_variable_set:cnnN {#1} { tl } { } x }
+\cs_new_protected:cpn { \c_@@_props_root_str .tl_gset_x:N } #1
+  { \@@_variable_set:NnnN #1 { tl } { g } x }
+\cs_new_protected:cpn { \c_@@_props_root_str .tl_gset_x:c } #1
+  { \@@_variable_set:cnnN {#1} { tl } { g } x }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[deprecated]
+%   {
+%     \keys_set_filter:nnnN, \keys_set_filter:nnVN,
+%     \keys_set_filter:nnvN, \keys_set_filter:nnoN
+%   }
+% \begin{macro}[deprecated]
+%   {
+%     \keys_set_filter:nnnnN, \keys_set_filter:nnVnN,
+%     \keys_set_filter:nnvnN, \keys_set_filter:nnonN
+%   }
+% \begin{macro}[deprecated]
+%   {
+%     \keys_set_filter:nnn, \keys_set_filter:nnV,
+%     \keys_set_filter:nnv, \keys_set_filter:nno
+%   }
+%   We need a transition here so for the present this is commented out:
+%   only needed for \texttt{latex-lab} code so this should not last for
+%   too long.
+%    \begin{macrocode}
+%\__kernel_patch_deprecation:nnNNpn { 2024-01-10 } { \keys_set_exclude_groups:nnn }
+\cs_new_protected:Npn \keys_set_filter:nnn { \keys_set_exclude_groups:nnn }
+\cs_generate_variant:Nn \keys_set_filter:nnn { nnV , nnv , nno }
+%\__kernel_patch_deprecation:nnNNpn { 2024-01-10 } { \keys_set_exclude_groups:nnnN }
+\cs_new_protected:Npn  \keys_set_filter:nnnN { \keys_set_exclude_groups:nnnN }
+\cs_generate_variant:Nn \keys_set_filter:nnnN { nnV , nnv , nno }
+%\__kernel_patch_deprecation:nnNNpn { 2024-01-10 } { \keys_set_exclude_groups:nnnnN }
+\cs_new_protected:Npn  \keys_set_filter:nnnnN { \keys_set_exclude_groups:nnnnN }
+\cs_generate_variant:Nn \keys_set_filter:nnnnN { nnV , nnv , nno }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3msg} functions}
+%
+%    \begin{macrocode}
+%<@@=msg>
+%    \end{macrocode}
+%
+% \begin{macro}[deprecated]{\msg_gset:nnnn, \msg_gset:nnn}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2024-02-13 } { \msg_set:nnnn }
+\cs_new_protected:Npn \msg_gset:nnnn { \msg_set:nnnn }
+\__kernel_patch_deprecation:nnNNpn { 2024-02-13 } { \msg_set:nnn }
+\cs_new_protected:Npn \msg_gset:nnn { \msg_set:nnn }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3pdf} functions}
+%
+%    \begin{macrocode}
+%<@@=pdf>
+%    \end{macrocode}
+%
+% \begin{variable}[deprecated]{\g_@@_object_prop}
+%   For tracking objects.
+%    \begin{macrocode}
+\prop_new:N \g_@@_object_prop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[deprecated]
+%   {\pdf_object_new:nn, \pdf_object_write:nn, \pdf_object_write:nx}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2022-08-30 } { [\pdf_object_new:n] }
+\cs_new_protected:Npn \pdf_object_new:nn #1#2
+  {
+    \prop_gput:Nnn \g_@@_object_prop {#1} {#2}
+    \@@_backend_object_new:n {#1}
+  }
+\__kernel_patch_deprecation:nnNNpn { 2022-08-30 } { [\pdf_object_write:n] }
+\cs_new_protected:Npn \pdf_object_write:nn #1#2
+  {
+    \exp_args:Nne \@@_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}
+%
+% \subsection{Deprecated \pkg{l3prg} functions}
+%
+%    \begin{macrocode}
+%<@@=cs>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP, noTF, deprecated]{\bool_case_true:n}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2023-05-03 } { \bool_case:n }
+\cs_new:Npn \bool_case_true:n { \bool_case:n }
+\__kernel_patch_deprecation:nnNNpn { 2023-05-03 } { \bool_case:nT }
+\cs_new:Npn \bool_case_true:nT { \bool_case:nT }
+\__kernel_patch_deprecation:nnNNpn { 2023-05-03 } { \bool_case:nF }
+\cs_new:Npn \bool_case_true:nF { \bool_case:nF }
+\__kernel_patch_deprecation:nnNNpn { 2023-05-03 } { \bool_case:nTF }
+\cs_new:Npn \bool_case_true:nTF { \bool_case:nTF }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3str} functions}
+%
+%    \begin{macrocode}
+%<@@=str>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP, deprecated]
+%   {
+%     \str_lower_case:n, \str_lower_case:f,
+%     \str_upper_case:n, \str_upper_case:f,
+%     \str_fold_case:n,  \str_fold_case:V
+%   }
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_lowercase:n }
+\cs_new:Npn \str_lower_case:n { \str_lowercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_lowercase:f }
+\cs_new:Npn \str_lower_case:f { \str_lowercase:f }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_uppercase:n }
+\cs_new:Npn \str_upper_case:n { \str_uppercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_uppercase:f }
+\cs_new:Npn \str_upper_case:f { \str_uppercase:f }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:n }
+\cs_new:Npn \str_fold_case:n { \str_casefold:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:V }
+\cs_new:Npn \str_fold_case:V { \str_casefold:V }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, deprecated]
+%   {\str_foldcase:n,  \str_foldcase:V}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2020-10-17 } { \str_casefold:n }
+\cs_new:Npn \str_foldcase:n { \str_casefold:n }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_casefold:V }
+\cs_new:Npn \str_foldcase:V { \str_casefold:V }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, deprecated]
+%   {\str_declare_eight_bit_encoding:nnn}
+%   This command was made internal, with one more argument.  There is no
+%   easy way to compute a reasonable value for that extra argument so we
+%   take a value that is big enough to accommodate all of Unicode.
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2020-08-20 } { }
+\cs_new_protected:Npn \str_declare_eight_bit_encoding:nnn #1
+  { \@@_declare_eight_bit_encoding:nnnn {#1} { 1114112 } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3seq} functions}
+%
+%    \begin{macrocode}
+%<@@=seq>
+%    \end{macrocode}
+%
+% \begin{macro}[deprecated]{\seq_indexed_map_inline:Nn}
+% \begin{macro}[EXP, deprecated]{ \seq_indexed_map_function:NN}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2020-06-18 } { \seq_map_indexed_inline:Nn }
+\cs_new_protected:Npn \seq_indexed_map_inline:Nn { \seq_map_indexed_inline:Nn }
+\__kernel_patch_deprecation:nnNNpn { 2020-06-18 } { \seq_map_indexed_function:NN }
+\cs_new:Npn \seq_indexed_map_function:NN { \seq_map_indexed_function:NN }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[deprecated]{\seq_mapthread_function:NNN}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2023-05-10 } { \seq_map_pairwise_function:NNN }
+\cs_new:Npn \seq_mapthread_function:NNN { \seq_map_pairwise_function:NNN }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[deprecated]{\seq_set_map_x:NNn, \seq_gset_map_x:NNn}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2023-10-26 } { \seq_set_map_e:NNn }
+\cs_new_protected:Npn \seq_set_map_x:NNn { \seq_set_map_e:NNn }
+\__kernel_patch_deprecation:nnNNpn { 2023-10-26 } { \seq_gset_map_e:NNn }
+\cs_new_protected:Npn \seq_gset_map_x:NNn { \seq_gset_map_e:NNn }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3sys} functions}
+%
+%    \begin{macrocode}
+%<@@=sys>
+%    \end{macrocode}
+%
+% \begin{macro}[deprecated]{\sys_load_deprecation:}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2021-01-11 } { (no~longer~required) }
+\cs_new_protected:Npn \sys_load_deprecation: { }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3text} functions}
+%
+%    \begin{macrocode}
+%<@@=text>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP, deprecated]{\text_titlecase:n}
+% \begin{macro}[EXP, deprecated]{\text_titlecase:nn}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2023-07-08 } { \text_titlecase_first:n }
+\cs_new:Npn \text_titlecase:n #1
+  { \text_titlecase_first:n { \text_lowercase:n {#1} } }
+\__kernel_patch_deprecation:nnNNpn { 2023-07-08 } { \text_titlecase_first:nn }
+\cs_new:Npn \text_titlecase:nn #1#2
+  { \text_titlecase_first:nn {#1} { \text_lowercase:n {#2} } }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3tl} functions}
+%
+%    \begin{macrocode}
+%<@@=tl>
+%    \end{macrocode}
+%
+% \begin{macro}[deprecated]
+%   {
+%     \tl_lower_case:n, \tl_lower_case:nn,
+%     \tl_upper_case:n, \tl_upper_case:nn,
+%     \tl_mixed_case:n, \tl_mixed_case:nn,
+%   }
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_lowercase:n }
+\cs_new:Npn \tl_lower_case:n #1
+  { \text_lowercase:n {#1} }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_lowercase:nn }
+\cs_new:Npn \tl_lower_case:nn #1#2
+  { \text_lowercase:nn {#1} {#2} }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_uppercase:n }
+\cs_new:Npn \tl_upper_case:n #1
+  { \text_uppercase:n {#1} }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_uppercase:nn }
+\cs_new:Npn \tl_upper_case:nn #1#2
+  { \text_uppercase:nn {#1} {#2} }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase_first:n }
+\cs_new:Npn \tl_mixed_case:n #1
+  { \text_titlecase_first:n {#1} }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase_first:nn }
+\cs_new:Npn \tl_mixed_case:nn #1#2
+  { \text_titlecase_first:nn {#1} {#2} }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[noTF, deprecated]{\tl_case:Nn, \tl_case:cn}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2022-05-23 } { \token_case_meaning:Nn }
+\cs_new:Npn \tl_case:Nn { \token_case_meaning:Nn }
+\__kernel_patch_deprecation:nnNNpn { 2022-05-23 } { \token_case_meaning:NnT }
+\cs_new:Npn \tl_case:NnT { \token_case_meaning:NnT }
+\__kernel_patch_deprecation:nnNNpn { 2022-05-23 } { \token_case_meaning:NnF }
+\cs_new:Npn \tl_case:NnF { \token_case_meaning:NnF }
+\__kernel_patch_deprecation:nnNNpn { 2022-05-23 } { \token_case_meaning:NnTF }
+\cs_new:Npn \tl_case:NnTF { \token_case_meaning:NnTF }
+\cs_generate_variant:Nn \tl_case:Nn   { c }
+\prg_generate_conditional_variant:Nnn \tl_case:Nn
+  { c } { T , F , TF }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[deprecated]{\tl_build_clear:N, \tl_build_gclear:N}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2023-10-18 } { \tl_build_begin:N }
+\cs_new_protected:Npn \tl_build_clear:N { \tl_build_begin:N }
+\__kernel_patch_deprecation:nnNNpn { 2023-10-18 } { \tl_build_gbegin:N }
+\cs_new_protected:Npn \tl_build_gclear:N { \tl_build_gbegin:N }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[deprecated]{\tl_build_get:NN}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2023-10-25 } { \tl_build_get_intermediate:NN }
+\cs_new_protected:Npn \tl_build_get:NN { \tl_build_get_intermediate:NN }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3token} functions}
+%
+%    \begin{macrocode}
+%<@@=char>
+%    \end{macrocode}
+%
+% \begin{macro}[EXP, deprecated]{\char_to_utfviii_bytes:n}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2022-10-09 } { [ \codepoint_generate:nn ] }
+\cs_new:Npn \char_to_utfviii_bytes:n { \__kernel_codepoint_to_bytes:n }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, deprecated]{\char_to_nfd:N, \char_to_nfd:n}
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2022-10-09 } { \codepoint_to_nfd:n }
+\cs_new:Npn \char_to_nfd:N #1 { \codepoint_to_nfd:n {`#1} }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-09 } { \codepoint_to_nfd:n }
+\cs_new:Npn \char_to_nfd:n { \codepoint_to_nfd:n }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, deprecated]
+%   {
+%     \char_lower_case:N, \char_upper_case:N,
+%     \char_mixed_case:Nn, \char_fold_case:N,
+%     \char_str_lower_case:N, \char_str_upper_case:N,
+%     \char_str_mixed_case:Nn, \char_str_fold_case:N,
+%   }
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_lowercase:n }
+\cs_new:Npn \char_lower_case:N { \text_lowercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_uppercase:n }
+\cs_new:Npn \char_upper_case:N { \text_uppercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase_first:n }
+\cs_new:Npn \char_mixed_case:N { \text_titlecase_first:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:n }
+\cs_new:Npn \char_fold_case:N { \str_casefold:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_lowercase:n }
+\cs_new:Npn \char_str_lower_case:N { \str_lowercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_uppercase:n }
+\cs_new:Npn \char_str_upper_case:N { \str_uppercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_titlecase:n }
+\cs_new:Npn \char_str_mixed_case:N { \str_titlecase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:n }
+\cs_new:Npn \char_str_fold_case:N { \str_casefold:n }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, deprecated]
+%   {
+%     \char_lowercase:N, \char_titlecase:N, \char_uppercase:N,
+%     \char_foldcase:N,
+%     \char_str_lowercase:N, \char_str_titlecase:N, \char_str_uppercase:N,
+%     \char_str_foldcase:N,
+%   }
+%    \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \text_lowercase:n }
+\cs_new:Npn \char_lowercase:N { \text_lowercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \text_uppercase:n }
+\cs_new:Npn \char_uppercase:N { \text_uppercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \text_titlecase_first:n }
+\cs_new:Npn \char_titlecase:N { \text_titlecase_first:n }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_casefold:n }
+\cs_new:Npn \char_foldcase:N { \str_casefold:n }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_lowercase:n }
+\cs_new:Npn \char_str_lowercase:N { \str_lowercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 }
+  { \tl_to_str:e { \text_titlecase_first:n } }
+\cs_new:Npn \char_str_titlecase:N #1
+  { \tl_to_str:e { \text_titlecase_first:n {#1} } }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_uppercase:n }
+\cs_new:Npn \char_str_uppercase:N { \str_uppercase:n }
+\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_casefold:n }
+\cs_new:Npn \char_str_foldcase:N { \str_casefold:n }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF, deprecated]
+%   {
+%     \peek_catcode_ignore_spaces:N, \peek_catcode_remove_ignore_spaces:N,
+%     \peek_charcode_ignore_spaces:N, \peek_charcode_remove_ignore_spaces:N,
+%     \peek_meaning_ignore_spaces:N, \peek_meaning_remove_ignore_spaces:N
+%   }
+%    A little extra fun here to deal with the expansion.
+%    \begin{macrocode}
+\tl_map_inline:nn
+  {
+    { catcode } { catcode_remove }
+    { charcode } { charcode_remove }
+    { meaning } { meaning_remove }
+  }
+  {
+    \use:e
+      {
+        \__kernel_patch_deprecation:nnNNpn { 2022-01-11 } { \peek_remove_spaces:n }
+        \cs_gset_protected:Npn \exp_not:c { peek_ #1 _ignore_spaces:NTF } ##1##2##3
+          {
+            \peek_remove_spaces:n
+              { \exp_not:c { peek_ #1 :NTF } ##1 {##2} {##3} }
+          }
+        \__kernel_patch_deprecation:nnNNpn { 2022-01-11 } { \peek_remove_spaces:n }
+        \cs_gset_protected:Npn \exp_not:c { peek_ #1 _ignore_spaces:NT } ##1##2
+          {
+            \peek_remove_spaces:n
+              { \exp_not:c { peek_ #1 :NT } ##1 {##2} }
+          }
+        \__kernel_patch_deprecation:nnNNpn { 2022-01-11 } { \peek_remove_spaces:n }
+        \cs_gset_protected:Npn \exp_not:c { peek_ #1 _ignore_spaces:NF } ##1##2
+          {
+            \peek_remove_spaces:n
+              { \exp_not:c { peek_ #1 :NF } ##1 {##2} }
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated \pkg{l3prop} functions}
+%
+% \begin{macro}[deprecated]
+%   {
+%     \prop_put_if_new:Nnn, \prop_put_if_new:NVn, \prop_put_if_new:NnV,
+%     \prop_put_if_new:cnn, \prop_put_if_new:cVn, \prop_put_if_new:cnV,
+%     \prop_gput_if_new:Nnn, \prop_gput_if_new:NVn, \prop_gput_if_new:NnV,
+%     \prop_gput_if_new:cnn, \prop_gput_if_new:cVn, \prop_gput_if_new:cnV
+%   }
+%    \begin{macrocode}
+%\__kernel_patch_deprecation:nnNNpn { 2024-03-30 } { \prop_put_if_not_in:Nnn }
+\cs_new_protected:Npn \prop_put_if_new:Nnn { \prop_put_if_not_in:Nnn }
+%\__kernel_patch_deprecation:nnNNpn { 2024-03-30 } { \prop_gput_if_not_in:Nnn }
+\cs_new_protected:Npn \prop_gput_if_new:Nnn { \prop_gput_if_not_in:Nnn }
+\cs_generate_variant:Nn \prop_put_if_new:Nnn
+  { NnV , NV , c , cnV , cV }
+\cs_generate_variant:Nn \prop_gput_if_new:Nnn
+  { NnV , NV , c , cnV , cV }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3deprecation.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3doc.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3doc.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex-dev/l3kernel/l3doc.dtx	2024-04-18 19:48:25 UTC (rev 70976)
@@ -0,0 +1,4802 @@
+% \iffalse meta-comment
+%
+%% File: l3doc.dtx
+%
+% Copyright (C) 1990-2024 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>
+\def\nameofplainTeX{plain}
+\ifx\fmtname\nameofplainTeX\else
+  \expandafter\begingroup
+\fi
+\input docstrip %
+\askforoverwritefalse
+\preamble
+
+Copyright (C) 1990-2024 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.
+
+\endpreamble
+% stop docstrip adding \endinput
+\postamble
+\endpostamble
+\generate{\file{l3doc.cls}{\from{l3doc.dtx}{class,cfg}}}
+%\generate{\file{l3doc.ist}{\from{l3doc.dtx}{docist}}}
+\ifx\fmtname\nameofplainTeX
+  \expandafter\endbatchfile
+\else
+  \expandafter\endgroup
+\fi
+%</driver>
+%
+%<*driver|class>
+\RequirePackage{calc}
+%</driver|class>
+%
+%<*driver>
+\documentclass{l3doc}
+\usepackage{framed}
+\begin{document}
+  \DocInput{l3doc.dtx}
+\end{document}
+%</driver>
+%
+% This isn't included in the typeset documentation because it's a bit
+% ugly:
+%<*class>
+\ProvidesExplClass{l3doc}{2024-04-11}{}
+  {L3 Experimental documentation class}
+%</class>
+% \fi
+%
+% \title{The \cls{l3doc} class -- experimental\thanks{%
+%    On popular request we now distribute the document for this
+%    experimental class.  However, please note that it is by no means
+%    in final state and is \emph{likely} to undergo modifications,
+%    even \emph{incompatible ones}! Thus, using it might therefore
+%    require you to do updates, if the class changes.}}
+%
+% \author{\Team}
+% \date{Released 2024-04-11}
+% \maketitle
+% \tableofcontents
+%
+% \begin{documentation}
+%
+%
+% \section{Introduction}
+%
+% Code and documentation for this class have been written prior to the
+% change of \pkg{doc} from version 2 to version 3, which already shows
+% how far behind this class currently is. So take the following
+% warning seriously please:
+%
+%  \begin{quote}
+% \textbf{It is much less stable than the main \pkg{expl3} packages.\\
+%   Use at own risk!}
+%  \end{quote}
+%
+% This is an ad-hoc class for documenting the \pkg{expl3} bundle, a
+% collection of modules or packages that make up \LaTeX3's programming
+% environment.  Eventually it will replace the \cls{ltxdoc} class for
+% \LaTeX3, but not before the good ideas in \pkg{hypdoc}, \cls{xdoc2},
+% \pkg{docmfp}, and \cls{gmdoc} are incorporated.
+%
+% It is written as a \enquote{self-contained} docstrip file: executing
+% |latex l3doc.dtx| generates the \file{l3doc.cls} file and typesets
+% this documentation; execute |tex l3doc.dtx| to only generate
+% \file{l3doc.cls}.
+%
+% \section{Features of other packages}
+%
+% This class builds on the \pkg{ltxdoc} class and the \pkg{doc} package,
+% but in the time since they were originally written some improvements
+% and replacements have appeared that we would like to use as
+% inspiration.
+%
+% These packages or classes are \pkg{hypdoc}, \pkg{docmfp}, \pkg{gmdoc},
+% and \pkg{xdoc}.  I have summarised them below in order to work out
+% what sort of features we should aim at a minimum for \pkg{l3doc}.
+%
+% \subsection{The \pkg{hypdoc} package}
+%
+% This package provides hyperlink support for the \pkg{doc} package.  I
+% have included it in this list to remind me that cross-referencing
+% between documentation and implementation of methods is not very
+% good. (\emph{E.g.}, it would be nice to be able to automatically
+% hyperlink the documentation for a function from its implementation and
+% vice-versa.)
+%
+% \subsection{The \pkg{docmfp} package}
+%
+% \begin{itemize}
+%   \item Provides \cs{DescribeRoutine} and the \env{routine}
+%     environment (\emph{etc.}) for MetaFont and MetaPost code.
+%   \item Provides \cs{DescribeVariable} and the \env{variable}
+%     environment (\emph{etc.})  for more general code.
+%   \item Provides \cs{Describe} and the \env{Code} environment
+%     (\emph{etc.})  as a generalisation of the above two
+%     instantiations.
+%   \item Small tweaks to the DocStrip system to aid non-\LaTeX{} use.
+% \end{itemize}
+%
+% \subsection{The \pkg{xdoc2} package}
+%
+% \begin{itemize}
+%   \item Two-sided printing.
+%   \item \cs{NewMacroEnvironment}, \cs{NewDescribeEnvironment}; similar
+%     idea to \pkg{docmfp} but more comprehensive.
+%   \item Tons of small improvements.
+% \end{itemize}
+%
+% \subsection{The \pkg{gmdoc} package}
+%
+% Radical re-implementation of \pkg{doc} as a package or class.
+% \begin{itemize}
+%   \item Requires no |\begin{macrocode}| blocks!
+%   \item Automatically inserts |\begin{macro}| blocks!
+%   \item And a whole bunch of other little things.
+% \end{itemize}
+%
+% \section{Problems \& Todo}
+%
+% Problems at the moment:
+% (1)~not flexible in the types of things that can be documented;
+% (2)~no obvious link between the |\begin{function}| environment for
+%     documenting things to the |\begin{macro}| function that's used
+%     analogously in the implementation.
+%
+% The \env{macro} should probably be renamed to \env{function} when it
+% is used within an implementation section.  But they should have the
+% same syntax before that happens!
+%
+% Furthermore, we need another \enquote{layer} of documentation commands
+% to account for \enquote{user-macro} as opposed to
+% \enquote{code-functions}; the \pkg{expl3} functions should be
+% documented differently, probably, to the \pkg{ltcmd} user macros (at
+% least in terms of indexing).
+%
+% In no particular order, a list of things to do:
+% \begin{itemize}
+%   \item Rename \env{function}/\env{macro} environments to better
+%     describe their use.
+%   \item Generalise \env{function}/\env{macro} for documenting
+%     \enquote{other things}, such as environment names, package
+%     options, even keyval options.
+%   \item New function like \tn{part} but for files (remove awkward
+%     \enquote{File} as \tn{partname}).
+%   \item Something better to replace \cs{StopEventually}; I'm thinking
+%     two environments \env{documentation} and \env{implementation} that
+%     can conditionally typeset/ignore their material.  (This has been
+%     implemented but needs further consideration.)
+%   \item Hyperlink documentation and implementation of macros (see the
+%     \textsc{dtx} file of \pkg{svn-multi} v2 as an example).  This is
+%     partially done, now, but should be improved.
+% \end{itemize}
+%
+% \section{Documentation}
+%
+% \subsection{Configuration}
+%
+% Before class options are processed, \pkg{l3doc} loads a configuration
+% file \file{l3doc.cfg} if it exists, allowing you to customise the
+% behaviour of the class without having to change the documentation
+% source files.
+%
+% For example, to produce documentation on letter-sized paper instead of
+% the default A4 size, create \file{l3doc.cfg} and include the line
+% \begin{verbatim}
+% \PassOptionsToClass{letterpaper}{l3doc}
+% \end{verbatim}
+%
+% By default, \pkg{l3doc} selects the |T1| font encoding and loads the
+% Latin Modern fonts.  To prevent this, use the class option
+% |cm-default|.
+%
+% \subsection{Class options}
+%
+% The class recognises a number of options, some of which are generally
+% useful and some of which are aimed squarely at use by the kernel team only.
+%
+% \DescribeOption{full}
+% \DescribeOption{onlydoc}
+% When the \texttt{full} option is set (the standard setting), both the
+% documentation and implementation parts of the source are typeset. If on the
+% other hand the \texttt{onlydoc} option is set, only the documentation part
+% is typeset.
+%
+% \DescribeOption{lm-default}
+% Selects whether the standard font set up is Latin Modern in the \texttt{T1}
+% encoding (the standard setting) or leaves the font setup unchanged.
+%
+% \DescribeOption{kernel}
+% Determines whether \pkg{l3doc} treats internal functions and variables
+% belonging to |kernel| module as allowable in code, for instance
+% \cs{__kernel_tl_to_str:w}, \cs{c__kernel_expl_date_tl}, and
+% \cs{l__kernel_expl_bool}. In general,
+% \emph{no} internal material from outside the current module is allowed.
+% However, for bootstrapping the \pkg{expl3} kernel, a small number of
+% cross-module functions are needed. To suppress the error message that
+% would otherwise arise, the class option \texttt{kernel} may be given.
+%
+% \DescribeOption{check}
+% When the \texttt{check} option is given, the class will record all commands
+% defined and documented in a \texttt{\meta{name}.cmds} file. This will show
+% which are both documented and defined, which are only documented and which
+% are only defined. (Here, \enquote{defined} means listed using a
+% \texttt{macro} or \texttt{variable} environment in the implementation part of
+% the source file).
+%
+% \DescribeOption{checktest}
+% When \texttt{checktest} is given as an option, the class will check that each
+% function entry in the implementation part of the source is marked using
+% \cs{UnitTest}.
+%
+% \DescribeOption{show-notes}
+% \DescribeOption{hide-notes}
+% These complementary options determine if the information given using the
+% \cs{NB} and \cs{NOTE} commands is printed.
+%
+% \DescribeOption{cs-break}
+% \DescribeOption{cs-break-nohyphen}
+% The commands \cs{cmd} and \cs{cs} allow hyphenation of control sequences
+% after (most) underscores. By default, a hyphen is used to mark the
+% hyphenation, but this can be changed with the \texttt{cs-break-nohyphen}
+% class option. To disable hyphenation of control sequences entirely, use
+% \texttt{cs-break = false}.
+%
+% By default, class options
+% \begin{verbatim}
+%   full , check = false , checktest = false , lm-default
+% \end{verbatim}
+% are set.
+%
+% \subsection{Partitioning documentation and implementation}
+%
+% \pkg{doc} uses the \cs{OnlyDocumentation}/\cs{AlsoImplementation}
+% macros to guide the use of \cs{StopEventually}|{}|, which is intended
+% to be placed to partition the documentation and implementation within
+% a single \file{.dtx} file.
+%
+% This isn't very flexible, since it assumes that we \emph{always} want
+% to print the documentation.  For the \pkg{expl3} sources, I wanted to
+%  be able to input \file{.dtx} files in two modes: only displaying
+% the documentation, and only displaying the implementation.  For
+% example:
+% \begin{verbatim}
+% \DisableImplementation
+% \DocInput{l3basics,l3prg,...}
+% \EnableImplementation
+% \DisableDocumentation
+% \DocInputAgain
+% \end{verbatim}
+%
+% The idea being that the entire \pkg{expl3} bundle can be documented,
+% with the implementation included at the back.  Now, this isn't
+% perfect, but it's a start.
+%
+% Use |\begin{documentation}...\end{documentation}| around the
+% documentation, and |\begin{implementation}...\end{implementation}|
+% around the implementation.  The
+% \cs{EnableDocumentation}/\cs{EnableImplementation} causes them to
+% be typeset when the \file{.dtx} file is \cs{DocInput}; use
+% \cs{DisableDocumentation}/\cs{DisableImplementation} to omit the
+% contents of those environments.
+%
+% Note that \cs{DocInput} now takes comma-separated arguments, and
+% \cs{DocInputAgain} can be used to re-input all \file{.dtx} files
+% previously input in this way.
+%
+% \subsection{General text markup}
+%
+% Many of the commands in this section come from \pkg{ltxdoc} with some
+% improvements.
+%
+% \begin{function}{\cmd, \cs}
+%   \begin{syntax}
+%     \cmd{\cmd} \oarg{options} \meta{control sequence}\\
+%     \cs{cs} \oarg{options} \marg{csname}
+%   \end{syntax}
+%   These commands are provided to typeset control sequences.
+%   |\cmd\foo| produces \enquote{\cmd\foo} and |\cs{foo}| produces the
+%   same.  In general, \cs{cs} is more robust since
+%   it doesn't rely on catcodes being \enquote{correct} and is therefore
+%   recommended.
+%
+%   These commands are aware of the |@@| \pkg{DocStrip} syntax and
+%   replace such instances correctly in the typeset documentation.
+%   This only happens after a |%<@@=|\meta{module}|>| declaration.
+%
+%   Additionally, commands can be used in the argument of \cs{cs}.  For
+%   instance, |\cs{\meta{name}:\meta{signature}}| produces
+%   \cs[no-index]{\meta{name}:\meta{signature}}.
+%
+%   The \meta{options} are a key--value list which can contain the
+%   following keys:
+%   \begin{itemize}
+%     \item |index=|\meta{name}: the \meta{csname} is indexed as if
+%       one had written \cs{cs}\Arg{name}.
+%     \item |no-index|: the \meta{csname} is not indexed.
+%     \item |module=|\meta{module}: the \meta{csname} is indexed in
+%       the list of commands from the \meta{module}; the \meta{module}
+%       can in particular be |TeX| for \enquote{\TeX{} and \LaTeXe{}}
+%       commands, or empty for commands which should be placed in the
+%       main index.  By default, the \meta{module} is deduced
+%       automatically from the command name.
+%     \item |replace| is a boolean key (\texttt{true} by default) which
+%       indicates whether to replace |@@| as \pkg{DocStrip} does.
+%   \end{itemize}
+%   These commands allow hyphenation of control sequences after (most) underscores.
+%   By default, a hyphen is used to mark the hyphenation, but this can be changed with
+%   the \texttt{cs-break-nohyphen} class option.
+%   To disable hyphenation of control sequences entirely, use
+%   \texttt{cs-break = false}.
+% \end{function}
+%
+%
+% \begin{function}{\tn}
+%   \begin{syntax}
+%     \cs{tn} \oarg{options} \marg{csname}
+%   \end{syntax}
+%   Analoguous to \cs{cs} but intended for \enquote{traditional} \TeX{}
+%   or \LaTeXe{} commands; they are indexed accordingly.  This is in
+%   fact equivalent to \cs{cs} |[module=TeX, replace=false,|
+%   \meta{options}|]| \Arg{csname}.
+% \end{function}
+%
+% \begin{function}{\meta}
+%   \begin{syntax}
+%     \cs{meta} \Arg{name}
+%   \end{syntax}
+%   \cs{meta} typesets the \meta{name} italicised in \meta{angle
+%     brackets}.  Within a \env{function} environment or similar, angle
+%   brackets |<...>| are set up to be a shorthand for |\meta{...}|.
+%
+%   This function has additional functionality over its \pkg{ltxdoc}
+%   versions; underscores can be used to subscript material as in math
+%   mode.  For example, |\meta{arg_{xy}}| produces
+%   \enquote{\meta{arg_{xy}}}.
+% \end{function}
+%
+% \begin{function}{\Arg, \marg, \oarg, \parg}
+%   \begin{syntax}
+%     |\Arg| \Arg{name}
+%   \end{syntax}
+%   Typesets the \meta{name} as for \cs{meta} and wraps it in braces.
+%
+%   The \cs{marg}/\cs{oarg}/\cs{parg} versions follow from \pkg{ltxdoc}
+%   in being used for \enquote{mandatory} or \enquote{optional} or
+%   \enquote{picture} brackets as per \LaTeXe{} syntax.
+% \end{function}
+%
+% \begin{function}{\file, \env, \pkg, \cls}
+%   \begin{syntax}
+%     \cs{pkg} \Arg{name}
+%   \end{syntax}
+%   These all take one argument and are intended to be used as semantic
+%   commands for representing files, environments, package names, and
+%   class names, respectively.
+% \end{function}
+%
+% \begin{function}{\NB, \NOTE}
+%   \begin{syntax}
+%     \cs{NB} \marg{tag} \marg{comments}
+%     \verb|\begin{NOTE}| \marg{tag}
+%     \qquad\meta{comments}
+%     \verb|\end{NOTE}|
+%   \end{syntax}
+%   Make notes in the source that are not typeset by default. When the \verb|show-notes|
+%   class option is active, the comments are typeset in a detokenized and verbatim mode, respectively.
+% \end{function}
+%
+% \subsection{Describing functions in the documentation}
+%
+% \DescribeEnv{function}
+% \DescribeEnv{variable}
+% Two heavily-used environments are defined to describe \pkg{expl3} functions
+% and variables.  If describing a variable, use the latter environment; it
+% behaves identically to the \env{function} environment.
+% \DescribeEnv{syntax}
+% Both of the above environments are typically combined with the \env{syntax}
+% environment, to describe their syntax.
+% \begin{framed}
+%   \vspace{-\baselineskip}
+% \begin{verbatim}
+% \begin{function}{\package_function_one:N, \package_function_two:n}
+%   \begin{syntax}
+%     \cs{package_function_one:N} \meta{cs}
+%     \cs{package_function_two:n} \marg{Argument}
+%   \end{syntax}
+% Descriptive text here ...
+% \end{function}
+% \end{verbatim}
+%   \hrulefill
+%   \par
+%   \hspace*{0.25\textwidth}
+%   \begin{minipage}{0.5\textwidth}
+%     \begin{function}{\package_function_one:N, \package_function_two:n}
+%       \begin{syntax}
+%         \cs[no-index]{package_function_one:N} \meta{cs}
+%         \cs[no-index]{package_function_two:n} \marg{Argument}
+%       \end{syntax}
+%       \emph{Descriptive text here …}
+%     \end{function}
+%   \end{minipage}
+% \end{framed}
+%
+% Function environments take an optional argument to indicate whether
+% the function(s) it describes are expandable (use |EXP|) or
+% restricted-expandable (use |rEXP|) or defined in conditional forms
+% (use |TF|, |pTF|, or |noTF|).  Note that |pTF| implies |EXP| since
+% predicates must always be expandable, and that |noTF| means that the
+% function without |TF| should be documented in addition to |TF|.  For
+% the conditional forms |TF| and |pTF|, the argument of the
+% \env{function} environment is \emph{not} in fact a command that
+% exists: in the example below, \cs[no-index]{tl_if_empty:N} does not
+% exist, but its conditional forms \cs{tl_if_empty:NT},
+% \cs{tl_if_empty:NF}, \cs{tl_if_empty:NTF} and predicate form
+% \cs{tl_if_empty_p:N} exist:
+% \begin{framed}
+%   \vspace{-\baselineskip}
+% \begin{verbatim}
+% \begin{function}[pTF]{\tl_if_empty:N, \tl_if_empty:c}
+%   \begin{syntax}
+%     \cs{tl_if_empty_p:N} \meta{tl~var}
+%     \cs{tl_if_empty:NTF} \meta{tl~var} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests if the \meta{token list variable} is entirely empty
+%   (\emph{i.e.}~contains no tokens at all).
+% \end{function}
+% \end{verbatim}
+%   \hrulefill
+%   \par
+%   \hspace*{0.25\textwidth}
+%   \begin{minipage}{0.5\textwidth}
+%     \begin{function}[pTF]{\tl_if_empty:N, \tl_if_empty:c}
+%       \begin{syntax}
+%         \cs{tl_if_empty_p:N} \meta{tl~var}
+%         \cs{tl_if_empty:NTF} \meta{tl~var} \Arg{true code} \Arg{false code}
+%       \end{syntax}
+%       Tests if the \meta{token list variable} is entirely empty
+%       (\emph{i.e.}~contains no tokens at all).
+%     \end{function}
+%   \end{minipage}
+% \end{framed}
+%
+% \DescribeEnv{texnote}
+% This environment is used to call out sections within \env{function}
+% and similar environments that are only of interest to seasoned
+% \TeX{} developers.
+%
+% \subsection{Describing functions in the implementation}
+%
+% \DescribeEnv{macro}
+% The well-used environment from \LaTeXe{} for marking up the
+% implementation of macros/functions remains the \env{macro}
+% environment.  Some changes in \pkg{l3doc}: it now accepts
+% comma-separated lists of functions, to avoid a very large number of
+% consecutive |\end{macro}| statements.
+% Spaces and new lines are ignored (the option |[verb]| prevents this).
+% \begin{verbatim}
+% % \begin{macro}{\foo:N, \foo:c}
+% %   \begin{macrocode}
+% ... code for \foo:N and \foo:c ...
+% %   \end{macrocode}
+% % \end{macro}
+% \end{verbatim}
+% If you are documenting an auxiliary macro, it's generally not
+% necessary to highlight it as much and you also don't need to check it
+% for, say, having a test function and having a documentation chunk
+% earlier in a \env{function} environment.  \pkg{l3doc} will pick up these
+% cases from the presence of |__| in the name, or you may force marking
+% as internal by using |\begin{macro}[int]| to mark it as such. The margin
+% call-out is then printed in grey for such cases.
+%
+% For documenting \pkg{expl3}-type conditionals, you may also pass this
+% environment a |TF| option (and omit it from the function name) to
+% denote that the function is provided with |T|, |F|, and |TF| suffixes.
+% A similar |pTF| option prints both |TF| and |_p| predicate forms.
+% An option |noTF| prints both the |TF| forms and a form with neither
+% |T| nor |F|, to document functions such as \cs[no-index]{prop_get:NN}
+% which also have conditional forms (\cs[no-index]{prop_get:NNTF}).
+%
+% In a very small number of cases, there is no user documentation for
+% a \enquote{public} function. In these rare cases, the option
+% |no-user-doc| may be added to suppress the undefined reference that
+% would otherwise then arises.
+%
+% \DescribeMacro{\TestFiles}
+% \cs{TestFiles}\marg{list of files} is used to indicate which test
+% files are used for the current code; they are printed in the
+% documentation.
+%
+% \DescribeMacro{\UnitTested}
+% Within a \env{macro} environment, it is a good idea to mark whether a
+% unit test has been created for the commands it defines.  This is
+% indicated by writing \cs{UnitTested} anywhere within |\begin{macro}|
+%   \dots |\end{macro}|.
+%
+% If the class option |checktest| is enabled, then it is an \emph{error}
+% to have a \env{macro} environment without a call to
+% \file{Testfiles}.  This is intended for large packages such as
+% \pkg{expl3} that should have absolutely comprehensive tests suites and
+% whose authors may not always be as sharp at adding new tests with new
+% code as they should be.
+%
+% \DescribeMacro{\TestMissing}
+% If a function is missing a test, this may be flagged by writing (as
+% many times as needed) \cs{TestMissing} \marg{explanation of test
+%   required}.  These missing tests are summarised in the listing
+% printed at the end of the compilation run.
+%
+% \DescribeEnv{variable}
+% When documenting variable definitions, use the \env{variable}
+% environment instead.  Here it behaves identically to the
+% \env{macro} environment, except that if the class option |checktest|
+% is enabled, variables are not required to have a test file.
+%
+% \DescribeEnv{arguments}
+% Within a \env{macro} environment, you may use the \env{arguments}
+% environment to describe the arguments taken by the function(s).  It
+% behaves like a modified enumerate environment.
+% \begin{verbatim}
+% % \begin{macro}{\foo:nn, \foo:VV}
+% % \begin{arguments}
+% %   \item Name of froozle to be frazzled
+% %   \item Name of muble to be jubled
+% % \end{arguments}
+% %   \begin{macrocode}
+% ... code for \foo:nn and \foo:VV ...
+% %   \end{macrocode}
+% % \end{macro}
+% \end{verbatim}
+%
+%
+% \subsection{Keeping things consistent}
+%
+% Whenever a function is either documented or defined with
+% \env{function} and \env{macro} respectively, its name is stored in a
+% sequence for later processing.
+%
+% At the end of the document (\emph{i.e.}, after the \file{.dtx} file
+% has finished processing), the list of names is analysed to check
+% whether all defined functions have been documented and vice versa. The
+% results are printed in the console output.
+%
+% If you need to do more serious work with these lists of names, take a
+% look at the implementation for the data structures and methods used to
+% store and access them directly.
+%
+% \subsection{Documenting templates}
+%
+% The following macros are provided for documenting templates; might end
+% up being something completely different but who knows.
+% \begin{quote}\parskip=0pt\obeylines
+%   |\begin{TemplateInterfaceDescription}| \Arg{template type name}
+%   |  \TemplateArgument{none}{---}|
+%   \textsc{or one or more of these:}
+%   |  \TemplateArgument| \Arg{arg no} \Arg{meaning}
+%   \textsc{and}
+%   |\TemplateSemantics|
+%   |  | \meta{text describing the template type semantics}
+%   |\end{TemplateInterfaceDescription}|
+% \end{quote}
+%
+% \begin{quote}\parskip=0pt\obeylines
+%   |\begin{TemplateDescription}| \Arg{template type name} \Arg{name}
+%   \textsc{one or more of these:}
+%   |  \TemplateKey| \marg{key name} \marg{type of key}
+%   |    |\marg{textual description of meaning}
+%   |    |\marg{default value if any}
+%   \textsc{and}
+%   |\TemplateSemantics|
+%   |  | \meta{text describing special additional semantics of the template}
+%   |\end{TemplateDescription}|
+% \end{quote}
+%
+% \begin{quote}\parskip=0pt\obeylines
+%   |\begin{InstanceDescription}| \oarg{text to specify key column width (optional)}
+%   \hfill\marg{template type name}\marg{instance name}\marg{template name}
+%   \textsc{one or more of these:}
+%   |  \InstanceKey| \marg{key name} \marg{value}
+%   \textsc{and}
+%   |\InstanceSemantics|
+%   |  | \meta{text describing the result of this instance}
+%   |\end{InstanceDescription}|
+% \end{quote}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3doc} implementation}
+%
+%    \begin{macrocode}
+%<*class>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=codedoc>
+%    \end{macrocode}
+%
+% \subsection{Variables}
+%
+% \begin{variable}{\g_docinput_clist}
+%   The list of files which have been input through \cs{DocInput}.
+%    \begin{macrocode}
+\clist_new:N \g_docinput_clist
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_doc_functions_seq, \g_doc_macros_seq}
+%   All functions documented through \env{function}, and all macros
+%   introduced through \env{macro}.  They can be compared to see what
+%   documentation or code is missing.
+%    \begin{macrocode}
+\seq_new:N \g_doc_functions_seq
+\seq_new:N \g_doc_macros_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_detect_internals_bool, \l_@@_detect_internals_tl}
+%   If \texttt{true}, \pkg{l3doc} will check for use of internal
+%   commands \cs[no-index]{__\meta{pkg}_\ldots{}} from other packages in
+%   the argument of the \texttt{macro} environment, and in the code typeset in
+%   \texttt{macrocode} environments, but not in~\cs{cs}.  Also a token list
+%   to store temporary data for this purpose.
+%    \begin{macrocode}
+\bool_new:N \l_@@_detect_internals_bool
+\bool_set_true:N \l_@@_detect_internals_bool
+\tl_new:N \l_@@_detect_internals_tl
+\tl_new:N \l_@@_detect_internals_cs_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_output_coffin}
+%   The \env{function} environment is typeset by combining coffins
+%   containing various pieces (function names, description, \emph{etc.})
+%   into this coffin.
+%    \begin{macrocode}
+\coffin_new:N \l_@@_output_coffin
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {\l_@@_functions_coffin, \l_@@_descr_coffin, \l_@@_syntax_coffin}
+%   These coffins contain respectively the list of function names
+%   (argument of the \env{function} environment), the text between
+%   |\begin{function}| and |\end{function}|, and the syntax given in the
+%   \env{syntax} environment.
+%    \begin{macrocode}
+\coffin_new:N \l_@@_functions_coffin
+\coffin_new:N \l_@@_descr_coffin
+\coffin_new:N \l_@@_syntax_coffin
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_syntax_box}
+%   The contents of the \env{syntax} environment are typeset in this box
+%   before being transferred to \cs{l_@@_syntax_coffin}.
+%    \begin{macrocode}
+\box_new:N \g_@@_syntax_box
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_in_function_bool}
+%   True when inside a \texttt{function} or \texttt{variable}
+%   environment.  Used by the \texttt{syntax} environment to determine
+%   its behaviour.
+%    \begin{macrocode}
+\bool_new:N \l_@@_in_function_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_long_name_bool, \l_@@_trial_width_dim}
+%   The boolean \cs{l_@@_long_name_bool} is \texttt{true} if the width
+%   \cs{l_@@_trial_width_dim} of the coffin \cs{l_@@_functions_coffin}
+%   (containing the current function names) is bigger than the space
+%   available in the margin.
+%    \begin{macrocode}
+\bool_new:N \l_@@_long_name_bool
+\dim_new:N \l_@@_trial_width_dim
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_nested_macro_int}
+%   The nesting of \env{macro} environments (this is now~$0$ outside a
+%   \env{macro} environment).
+%    \begin{macrocode}
+\int_new:N \l_@@_nested_macro_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {
+%     \l_@@_macro_tested_bool,
+%     \g_@@_missing_tests_prop,
+%     \g_@@_not_tested_seq,
+%     \g_@@_testfiles_seq,
+%   }
+%   A boolean describing whether the current macro has tests, and some
+%   global structures which contain information about test files and
+%   which tests are missing.
+%    \begin{macrocode}
+\bool_new:N \l_@@_macro_tested_bool
+\prop_new:N \g_@@_missing_tests_prop
+\seq_new:N \g_@@_not_tested_seq
+\seq_new:N \g_@@_testfiles_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {
+%     \l_@@_macro_deprecated_bool ,
+%     \l_@@_macro_internal_bool,
+%     \l_@@_macro_nodoc_bool ,
+%     \l_@@_macro_TF_bool,
+%     \l_@@_macro_pTF_bool,
+%     \l_@@_macro_noTF_bool,
+%     \l_@@_macro_EXP_bool,
+%     \l_@@_macro_rEXP_bool,
+%     \l_@@_macro_var_bool,
+%     \l_@@_override_module_tl,
+%     \l_@@_macro_documented_tl,
+%   }
+%   Contain information about some options of function/macro
+%   environments.  We initialize \cs{l_@@_override_module_tl} to avoid
+%   overriding module names by an empty name (meaning no module).
+%    \begin{macrocode}
+\bool_new:N \l_@@_macro_deprecated_bool
+\bool_new:N \l_@@_macro_internal_bool
+\bool_new:N \l_@@_macro_nodoc_bool
+\bool_new:N \l_@@_macro_TF_bool
+\bool_new:N \l_@@_macro_pTF_bool
+\bool_new:N \l_@@_macro_noTF_bool
+\bool_new:N \l_@@_macro_EXP_bool
+\bool_new:N \l_@@_macro_rEXP_bool
+\bool_new:N \l_@@_macro_var_bool
+\tl_new:N \l_@@_override_module_tl
+\tl_set:Nn \l_@@_override_module_tl { \q_no_value }
+\tl_new:N \l_@@_macro_documented_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {
+%     \g_@@_lmodern_bool,
+%     \g_@@_checkfunc_bool,
+%     \g_@@_checktest_bool,
+%     \g_@@_cs_break_bool,
+%     \g_@@_show_notes_bool,
+%     \g_@@_kernel_bool
+%   }
+%   Information about package options.
+%    \begin{macrocode}
+\bool_new:N \g_@@_lmodern_bool
+\bool_new:N \g_@@_checkfunc_bool
+\bool_new:N \g_@@_checktest_bool
+\bool_new:N \g_@@_kernel_bool
+\bool_new:N \g_@@_cs_break_bool
+\bool_new:N \g_@@_show_notes_bool
+\bool_gset_true:N \g_@@_cs_break_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_tmpa_tl, \l_@@_tmpb_tl, \l_@@_tmpa_int, \l_@@_tmpa_seq}
+%   Some temporary variables.
+%    \begin{macrocode}
+\tl_new:N \l_@@_tmpa_tl
+\tl_new:N \l_@@_tmpb_tl
+\int_new:N \l_@@_tmpa_int
+\int_new:N \l_@@_tmpa_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_names_block_tl}
+%   List of local sequence variables (produced through
+%   \cs{@@_lseq_name:n}), one for each set of variants in a
+%   \env{function} or \env{macro} environment.  More precisely these
+%   sequences are named after the base forms, such as \cs{clist_count:n}
+%   or \cs{clist_count:N} (which are not variants).  Each of these
+%   sequences have the base name (without any signature) as their first
+%   item, followed by the list of variant's signatures, or
+%   \cs{scan_stop:} to denote the absence of signature (no colon).
+%    \begin{macrocode}
+\tl_new:N \l_@@_names_block_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_variants_seq}
+%   Stores rather temporarily the list of variants (signatures only) of
+%   a function/macro that is being documented.  It is global because we
+%   need it to keep its value throughout cells of an alignment.
+%    \begin{macrocode}
+\seq_new:N \g_@@_variants_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_names_verb_bool}
+%   Set to |true| if the main argument of a macro/function environment
+%   should be used as is, without removing any comma or space.
+%    \begin{macrocode}
+\bool_new:N \l_@@_names_verb_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_names_seq}
+%   List of functions/environments/\ldots{} appearing as arguments of a
+%   given \env{function} or \env{macro} environment.  These are the
+%   names after conversion of |_@@| and |@@| to |__|\meta{module name}
+%   and other sanitizing.
+%    \begin{macrocode}
+\seq_new:N \l_@@_names_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_nested_names_seq}
+%   Collects all macros in nested \env{macro} environments, to use them
+%   in the \enquote{End definition} text.
+%    \begin{macrocode}
+\seq_new:N \g_@@_nested_names_seq
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {
+%     \l_@@_index_macro_tl, \l_@@_index_key_tl,
+%     \l_@@_index_module_tl, \l_@@_index_internal_bool,
+%     \l_@@_macro_do_not_index_tl
+%   }
+%   When analyzing a control sequence found within a \env{macrocode}
+%   environment, \cs{l_@@_index_macro_tl} holds the control sequence
+%   (partially a string), \cs{l_@@_index_key_tl} holds the future
+%   sort key in the index, and \cs{l_@@_index_module_tl} is the
+%   subindex in which the control sequence should be listed.
+%   \cs{l_@@_index_internal_bool} indicates when the control sequence is
+%   internal and should be indexed in a slightly different subindex.
+%   Finally, \cs{l_@@_macro_do_not_index_tl} indicates control sequences
+%   which should not be indexed in a specifiv \env{macro} envronment.
+%    \begin{macrocode}
+\tl_new:N \l_@@_index_macro_tl
+\tl_new:N \l_@@_index_key_tl
+\tl_new:N \l_@@_index_module_tl
+\tl_new:N \l_@@_macro_do_not_index_tl
+\bool_new:N \l_@@_index_internal_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_module_name_tl}
+%   The module name, set when reading a line |<@@=|\meta{module}|>|.
+%    \begin{macrocode}
+\tl_new:N \g_@@_module_name_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_@@_iow_rule_tl, \c_@@_iow_midrule_tl}
+%   $40$~equal signs.
+%    \begin{macrocode}
+\tl_const:Nn \c_@@_iow_rule_tl
+  { ======================================== }
+\tl_const:Nn \c_@@_iow_mid_rule_tl
+  { -------------------------------------- }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {\l_@@_macro_box, \l_@@_macro_index_box, \l_@@_macro_int}
+%   A vertical box in which the names given to the macro environment are
+%   typeset, a horizontal box in which we store the targets created by
+%   indexing commands, and the number of macros so far (including those
+%   from surrounding \env{macro} environments).
+%    \begin{macrocode}
+\box_new:N \l_@@_macro_box
+\box_new:N \l_@@_macro_index_box
+\int_new:N \l_@@_macro_int
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {
+%     \l_@@_cmd_tl,
+%     \l_@@_cmd_index_tl,
+%     \l_@@_cmd_module_tl,
+%     \l_@@_cmd_noindex_bool,
+%     \l_@@_cmd_replace_bool,
+%   }
+%   Variables used to control the behaviour of \cs{cmd}, \cs{cs} and
+%   \cs{tn}.
+%    \begin{macrocode}
+\tl_new:N \l_@@_cmd_tl
+\tl_new:N \l_@@_cmd_index_tl
+\tl_new:N \l_@@_cmd_module_tl
+\bool_new:N \l_@@_cmd_noindex_bool
+\bool_new:N \l_@@_cmd_replace_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_in_implementation_bool}
+%   This boolean is \texttt{true} within the \env{implementation}
+%   environment, and \texttt{false} anywhere else.
+%    \begin{macrocode}
+\bool_new:N \l_@@_in_implementation_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+%   {
+%     \g_@@_typeset_documentation_bool,
+%     \g_@@_typeset_implementation_bool
+%   }
+%   These booleans control whether the documentation/implementation
+%   should be typeset.  By default both should be.
+%    \begin{macrocode}
+\bool_new:N \g_@@_typeset_documentation_bool
+\bool_new:N \g_@@_typeset_implementation_bool
+\bool_set_true:N \g_@@_typeset_documentation_bool
+\bool_set_true:N \g_@@_typeset_implementation_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_base_name_tl, \l_@@_variants_prop}
+%   The name of the macro which is being documented (without its
+%   signature), and a property list mapping base forms of variants to
+%   all variants which have the same base form.
+%    \begin{macrocode}
+\tl_new:N \g_@@_base_name_tl
+\prop_new:N \l_@@_variants_prop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_function_label_clist, \l_@@_no_label_bool}
+%   Option of a \env{function} environment which replaces the label that
+%   would normally be inserted by labels for the given list of control
+%   sequences.  This is only useful to avoid duplicate labels when a
+%   function's documentation appears multiple times.
+%    \begin{macrocode}
+\clist_new:N \l_@@_function_label_clist
+\bool_new:N \l_@@_no_label_bool
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_date_added_tl, \l_@@_date_updated_tl}
+%   Values of some options of the \env{function} environment.
+%    \begin{macrocode}
+\tl_new:N \l_@@_date_added_tl
+\tl_new:N \l_@@_date_updated_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_macro_argument_tl}
+%   Save the argument of a \env{macro} or \env{function} environment for
+%   use in error messages.
+%    \begin{macrocode}
+\tl_new:N \l_@@_macro_argument_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% ^^A Bruno: what does the next line do?
+%    \begin{macrocode}
+% \int_new:N \c at CodelineNo
+%    \end{macrocode}
+%
+% \subsection{Variants and helpers}
+%
+% \begin{macro}{\@@_tmpa:w, \@@_tmpb:w}
+%   Auxiliary macros for temporary use.
+%    \begin{macrocode}
+\cs_new_eq:NN \@@_tmpa:w ?
+\cs_new_eq:NN \@@_tmpb:w ?
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \seq_set_split:NoV,
+%     \tl_to_str:f
+%   }
+%   A few missing variants.
+%    \begin{macrocode}
+\cs_generate_variant:Nn \seq_set_split:Nnn { NoV }
+\cs_generate_variant:Nn \tl_to_str:n { f }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF]{\@@_if_almost_str:n}
+%   Used to test if the argument of |\cmd| or other macros to be indexed
+%   is almost a string or not: for instance this is \texttt{false} if |#1|
+%   contains |\meta{...}|.  The surprising |f|-expansion is there to
+%   cope with the case of |#1| starting with \cs{c_backslash_str}
+%   which should be expanded and considered to be \enquote{normal}.
+%    \begin{macrocode}
+\prg_new_protected_conditional:Npnn \@@_if_almost_str:n #1 { TF , T , F }
+  {
+    \int_compare:nNnTF
+      { \tl_count:n {#1} }
+      < { \tl_count:e { \tl_to_str:f {#1} } }
+      { \prg_return_false: }
+      { \prg_return_true: }
+  }
+\prg_generate_conditional_variant:Nnn \@@_if_almost_str:n { V } { T }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_trim_right:Nn, \@@_trim_right:No}
+%   Removes all material after |#2| in the token list variable~|#1|.
+%   Perhaps combine with \cs{@@_key_trim_module:n}?
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_trim_right:Nn #1#2
+  {
+    \cs_set:Npn \@@_tmp:w ##1 #2 ##2 \q_stop { \exp_not:n {##1} }
+    \__kernel_tl_set:Nx #1 { \exp_after:wN \@@_tmp:w #1 #2 \q_stop }
+  }
+\cs_generate_variant:Nn \@@_trim_right:Nn { No }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF]{\@@_str_if_begin:nn, \@@_str_if_begin:oo}
+%   True if the first string starts with the second.
+%    \begin{macrocode}
+\prg_new_protected_conditional:Npnn \@@_str_if_begin:nn #1#2 { TF , T , F }
+  {
+    \tl_if_in:ooTF
+      { \exp_after:wN \scan_stop: \tl_to_str:n {#1} }
+      { \exp_after:wN \scan_stop: \tl_to_str:n {#2} }
+      { \prg_return_true: }
+      { \prg_return_false: }
+  }
+\prg_generate_conditional_variant:Nnn \@@_str_if_begin:nn
+  { oo } { TF , T , F }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_replace_at_at:N}
+% \begin{macro}{\@@_replace_at_at_aux:Nn}
+%   The goal is to replace |@@| by the current module name.  We take
+%   advantage of this function to also detect internal macros.  If there is
+%   no \meta{module~name}, do nothing.  Otherwise, sanitize the catcodes
+%   of |@| and~|_|, temporarily change |@@@@| to |aa| with different catcodes and later to |@@|, and replace |__@@| and |_@@| and |@@| by
+%   |__|\meta{module~name}.  The result contains |_| with category
+%   code letter because this is what the |macrocode| environment
+%   expects.  Other use cases can apply \cs{tl_to_str:n} if needed.
+%   Note that we include spaces between the
+%   |@| in the code below, since it is also processed through the same
+%   replacement rules.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_replace_at_at:N #1
+  {
+    \tl_if_empty:NF \g_@@_module_name_tl
+      {
+        \exp_args:NNo \@@_replace_at_at_aux:Nn
+          #1 \g_@@_module_name_tl
+      }
+  }
+\cs_new_protected:Npe \@@_replace_at_at_aux:Nn #1#2
+  {
+    \tl_replace_all:Nnn #1 { \token_to_str:N @ } { @ }
+    \tl_replace_all:Nnn #1 { \token_to_str:N _ } { _ }
+    \tl_replace_all:Nnn #1 { @ @ @ @ } { \token_to_str:N a a }
+    \tl_replace_all:Nnn #1 { _ _ @ @ } { _ _ #2 }
+    \tl_replace_all:Nnn #1 {   _ @ @ } { _ _ #2 }
+    \tl_replace_all:Nnn #1 {     @ @ } { _ _ #2 }
+    \tl_replace_all:Nnn #1 { \token_to_str:N a a } { @ @ }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \@@_detect_internals:N,
+%     \@@_detect_internals_aux:N,
+%     \@@_if_detect_internals_ok:NF
+%   }
+%   After splitting at each |__| and removing the leading item from the
+%   sequence (since it does not follow |__|), remove everything after
+%   any space or end-of-line to get a good approximation of the control
+%   sequence (for the warning message).  Then check if that starts with
+%   something allowed: |@@| module name and |:| or |_|, or if the
+%   relevant boolean is set |kernel_| (it seems safe to assume we will
+%   not define a |\__kernel:...| command).  For the message itself
+%   remove anything after any |_| or |:| (with either catcode) to get a
+%   guess of the module name.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_detect_internals:N #1
+  {
+    \bool_if:NT \l_@@_detect_internals_bool
+      { \@@_detect_internals_aux:N #1 }
+  }
+\group_begin:
+  \char_set_catcode_active:N \^^M
+  \cs_new_protected:Npn \@@_detect_internals_aux:N #1
+    {
+      \tl_set_eq:NN \l_@@_detect_internals_tl #1
+      \tl_replace_all:NVn \l_@@_detect_internals_tl \c_underscore_str { _ }
+      \seq_set_split:NnV \l_@@_tmpa_seq { _ _ } \l_@@_detect_internals_tl
+      \seq_pop_left:NN \l_@@_tmpa_seq \l_@@_detect_internals_tl
+      \seq_map_variable:NNn \l_@@_tmpa_seq \l_@@_detect_internals_tl
+        {
+          \@@_trim_right:No \l_@@_detect_internals_tl
+            \c_catcode_active_space_tl
+          \@@_trim_right:Nn \l_@@_detect_internals_tl ^^M
+          \@@_if_detect_internals_ok:NF \l_@@_detect_internals_tl
+            {
+              \tl_set_eq:NN \l_@@_detect_internals_cs_tl \l_@@_detect_internals_tl
+              \@@_trim_right:Nn \l_@@_detect_internals_tl _
+              \@@_trim_right:Nn \l_@@_detect_internals_tl :
+              \@@_trim_right:No \l_@@_detect_internals_tl { \token_to_str:N : }
+              \msg_warning:nneee { l3doc } { foreign-internal }
+                { \tl_to_str:N \l_@@_detect_internals_cs_tl }
+                { \tl_to_str:N \l_@@_detect_internals_tl }
+                { \tl_to_str:N \g_@@_module_name_tl }
+            }
+        }
+    }
+\group_end:
+\prg_new_protected_conditional:Npnn \@@_if_detect_internals_ok:N #1 { F }
+  {
+    \@@_str_if_begin:ooTF {#1} { \g_@@_module_name_tl _ }
+      { \prg_return_true: }
+      {
+        \@@_str_if_begin:ooTF {#1} { \g_@@_module_name_tl : }
+          { \prg_return_true: }
+          {
+            \bool_if:NTF \g_@@_kernel_bool
+              {
+                \@@_str_if_begin:ooTF {#1} { kernel _ }
+                  { \prg_return_true: }
+                  { \prg_return_false: }
+              }
+              { \prg_return_false: }
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[rEXP]{\@@_signature_base_form:n}
+% \begin{macro}
+%   {\@@_signature_base_form_aux:n, \@@_signature_base_form_aux:w}
+%   Expands to the \enquote{base form} of the signature.  For instance,
+%   given |noxcfvV| it would obtain |nnnNnnn|, or given |ow| it would
+%   obtain |nw|.  The loop stops at the first token that is not
+%   recognized; the rest is enclosed in \cs{exp_not:n}.
+%    \begin{macrocode}
+\cs_new:Npn \@@_signature_base_form:n #1
+  { \@@_signature_base_form_aux:n #1 \q_stop }
+\cs_new:Npn \@@_signature_base_form_aux:n #1
+  {
+    \str_case:nnTF {#1}
+      {
+        { N } { N }
+        { c } { N }
+        { n } { n }
+        { o } { n }
+        { f } { n }
+        { e } { n }
+        { x } { n }
+        { V } { n }
+        { v } { n }
+      }
+      { \@@_signature_base_form_aux:n }
+      { \@@_signature_base_form_aux:w #1 }
+  }
+\cs_new:Npn \@@_signature_base_form_aux:w #1 \q_stop
+  { \exp_not:n {#1} }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_predicate_from_base:n}
+%   Get predicate from a function's base name.  The code is not broken
+%   by functions with no signature.  The |n|-type version can be used
+%   for keys and other non-control sequences.  The output after
+%   |e|-expansion is a string.
+%    \begin{macrocode}
+\cs_new:Npn \@@_predicate_from_base:n #1
+  {
+    \@@_get_function_name:n {#1}
+    \tl_to_str:n { _p: }
+    \@@_get_function_signature:n {#1}
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_split_function_do:nn, \@@_split_function_do:on}
+% \begin{macro}{\@@_get_function_name:n, \@@_get_function_signature:n}
+% \begin{macro}{\@@_split_function_auxi:w, \@@_split_function_auxii:w}
+%   Similar to internal functions defined in \pkg{l3basics}, but here we
+%   operate on strings directly rather than control sequences.
+%    \begin{macrocode}
+\cs_new:Npn \@@_get_function_name:n #1
+  { \@@_split_function_do:nn {#1} { \use_i:nnn } }
+\cs_new:Npn \@@_get_function_signature:n #1
+  { \@@_split_function_do:nn {#1} { \use_ii:nnn } }
+\cs_set_protected:Npn \@@_tmpa:w #1
+  {
+    \cs_new:Npn \@@_split_function_do:nn ##1
+      {
+        \exp_after:wN \@@_split_function_auxi:w
+        \tl_to_str:n {##1} \q_mark \c_true_bool
+        #1 \q_mark \c_false_bool
+        \q_stop
+      }
+    \cs_new:Npn \@@_split_function_auxi:w
+      ##1 #1 ##2 \q_mark ##3##4 \q_stop ##5
+      { \@@_split_function_auxii:w {##5} ##1 \q_mark \q_stop {##2} ##3 }
+    \cs_new:Npn \@@_split_function_auxii:w
+      ##1##2 \q_mark ##3 \q_stop
+      { ##1 {##2} }
+  }
+\exp_args:No \@@_tmpa:w { \token_to_str:N : }
+\cs_generate_variant:Nn \@@_split_function_do:nn { o }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[rEXP]{\@@_key_get_base:nN}
+%   Get the base form of a function and store it.  As part of getting
+%   the base form, change trailing |T| or |F| to |TF|, skipping that
+%   change if the function contains no colon to avoid changing for
+%   instance some names ending in \texttt{PDF} or similar.  The various
+%   letters |z| serve as end-delimiters different from any outcome of
+%   \cs{tl_to_str:n}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_key_get_base:nN #1#2
+  {
+    \@@_if_almost_str:nTF {#1}
+      {
+        \@@_key_get_base_TF:nN {#1} \l_@@_tmpa_tl
+        \__kernel_tl_set:Nx #2
+          { \@@_split_function_do:on \l_@@_tmpa_tl { \@@_base_form_aux:nnN } }
+      }
+      { \tl_set:Nn #2 {#1} }
+  }
+\cs_new:Npe \@@_key_get_base_TF:nN #1#2
+  {
+    \__kernel_tl_set:Nx #2 { \exp_not:N \tl_to_str:n {#1} }
+    \tl_if_in:NoF #2 { \tl_to_str:n {:} }
+      { \exp_not:N \prg_break: }
+    \tl_if_in:onT { #2 z } { \tl_to_str:n {TF} z }
+      { \exp_not:N \prg_break: }
+    \tl_if_in:onT { #2 z } { \tl_to_str:n {T} z }
+      {
+        \tl_put_right:Nn #2 { \tl_to_str:n {F} }
+        \exp_not:N \prg_break:
+      }
+    \tl_if_in:onT { #2 z } { \tl_to_str:n {F} z }
+      {
+        \tl_put_right:Nn #2 { z }
+        \tl_replace_once:Nnn #2 { \tl_to_str:n {F} z } { \tl_to_str:n {TF} }
+        \exp_not:N \prg_break:
+      }
+    \exp_not:N \prg_break_point:
+  }
+\cs_new:Npn \@@_base_form_aux:nnN #1#2#3
+  {
+    \exp_not:n {#1}
+    \bool_if:NT #3
+      {
+        \token_to_str:N :
+        \bool_lazy_or:nnTF
+            { \str_if_eq_p:nn { #1 ~ } { \exp_args } }
+            { \str_if_eq_p:nn { #1 ~ } { \exp_last_unbraced } }
+          { \exp_not:n {#2} }
+          { \@@_signature_base_form:n {#2} }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_base_form_signature_do:nnn}
+%   Do |#2{#1}| if there is no signature, or if |#1| contains two colons
+%   in a row (this covers the weird function |\::N| and so on).
+%   Otherwise apply |#3| with the following two arguments: the base form
+%   of |#1|, and the original signature with an extra pair of braces.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_base_form_signature_do:nnn #1#2#3
+  {
+    \@@_split_function_do:nn {#1}
+      { \@@_base_form_aux:nnnnnN {#1} {#2} {#3} }
+  }
+\cs_new_protected:Npn \@@_base_form_aux:nnnnnN #1#2#3#4#5#6
+  {
+    \bool_if:NTF #6
+      {
+        \tl_if_head_eq_charcode:nNTF {#4} :
+          { #2 {#1} }
+          {
+            \use:e
+              {
+                \exp_not:n {#3}
+                { \@@_base_form_aux:nnN {#4} {#5} #6 }
+              }
+                {#4} {#5}
+          }
+      }
+      { #2 {#1} }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_date_compare:nNn}
+% \begin{macro}{\@@_date_compare_aux:nnnNnnn, \@@_date_compare_aux:w}
+%   Expects |#1| and |#3| to be dates in the format YYYY-MM-DD (but
+%   accepts YYYY or YYYY-MM too).  Compares them using |#2| (one of |<|,
+%   |=|, |>|), filling in zeros for missing data.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \@@_date_compare:nNn #1#2#3 { TF , T , F , p }
+  { \@@_date_compare_aux:w #1--- \q_mark #2 #3--- \q_stop }
+\cs_new:Npn \@@_date_compare_aux:w
+    #1 - #2 - #3 - #4 \q_mark #5 #6 - #7 - #8 - #9 \q_stop
+  {
+    \@@_date_compare_aux:nnnNnnn
+      { \tl_if_empty:nTF {#1} { 0 } {#1} }
+      { \tl_if_empty:nTF {#2} { 0 } {#2} }
+      { \tl_if_empty:nTF {#3} { 0 } {#3} }
+      #5
+      { \tl_if_empty:nTF {#6} { 0 } {#6} }
+      { \tl_if_empty:nTF {#7} { 0 } {#7} }
+      { \tl_if_empty:nTF {#8} { 0 } {#8} }
+  }
+\cs_new:Npn \@@_date_compare_aux:nnnNnnn #1#2#3#4#5#6#7
+  {
+    \int_compare:nNnTF {#1} = {#5}
+      {
+        \int_compare:nNnTF {#2} = {#6}
+          {
+            \int_compare:nNnTF {#3} #4 {#7}
+              { \prg_return_true: } { \prg_return_false: }
+          }
+          {
+            \int_compare:nNnTF {#2} #4 {#6}
+              { \prg_return_true: } { \prg_return_false: }
+          }
+      }
+      {
+        \int_compare:nNnTF {#1} #4 {#5}
+          { \prg_return_true: } { \prg_return_false: }
+      }
+    \use_none:n
+    \q_stop
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_gprop_name:n, \@@_lseq_name:n}
+%   We need to keep track of some information about control sequences
+%   (and other strings) that are being (or have been) documented.  Some
+%   is stored into global props and some into local seqs, whose name
+%   does not follow conventions: it is \cs[no-index]{g_@@} or
+%   \cs[no-index]{l_@@} followed by a space and by the string, which can
+%   be arbitrary.  We cannot reasonably use a single big |prop| for
+%   speed reasons.
+%    \begin{macrocode}
+\cs_new:Npn \@@_gprop_name:n #1 { g_@@ ~ \tl_to_str:n {#1} }
+\cs_new:Npn \@@_lseq_name:n #1 { l_@@ ~ \tl_to_str:n {#1} }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+%    \begin{macrocode}
+\msg_new:nnnn { l3doc } { no-signature-TF }
+  { Function/macro~'#1'~cannot~be~turned~into~a~conditional. }
+  {
+    A~function~or~macro~environment~with~option~pTF,~TF~or~noTF~
+    received~the~argument~'#1'.~This~function's~name~has~no~
+    ':'~hence~it~is~not~clear~where~to~add~'_p'~or~'TF'.~
+    Please~follow~expl3~naming~conventions.
+  }
+\msg_new:nnn { l3doc } { date-format }
+  { The~date~'#1'~should~be~given~in~YYYY-MM-DD~format. }
+\msg_new:nnn { l3doc } { future-date }
+  { The~added/updated~date~'#2'~of~'#1'~is~in~the~future. }
+\msg_new:nnn { l3doc } { syntax-nested-function }
+  {
+    The~'syntax'~environment~should~be~used~in~the~
+    innermost~'function'~environment.
+  }
+\msg_new:nnn { l3doc } { multiple-syntax }
+  {
+    The~'syntax'~environment~should~only~be~used~once~in~
+    a~'function'~environment.
+  }
+\msg_new:nnn { l3doc } { deprecated-option }
+  { The~option~'#1'~has~been~deprecated~for~'#2'. }
+\msg_new:nnn { l3doc } { foreign-internal }
+  {
+    A~control~sequence~of~the~form~'...__#1'~was~used.~
+    It~should~only~be~used~in~the~module~'#2'
+    \tl_if_empty:nF {#3} { ,~not~in~'#3' } .
+  }
+%    \end{macrocode}
+%
+% \subsection{Options and configuration}
+%
+%    \begin{macrocode}
+\DeclareKeys [ l3doc / options ]
+  {
+    a5paper .code:n = \@latexerr { Option~not~supported } { } ,
+    full .code:n =
+      {
+        \bool_gset_true:N \g_@@_typeset_documentation_bool
+        \bool_gset_true:N \g_@@_typeset_implementation_bool
+      } ,
+    onlydoc .code:n = 
+      {
+        \bool_gset_true:N \g_@@_typeset_documentation_bool
+        \bool_gset_false:N \g_@@_typeset_implementation_bool
+      } ,
+    check .bool_gset:N = \g_@@_checkfunc_bool ,
+    checktest .bool_gset:N = \g_@@_checktest_bool ,
+    kernel .bool_gset:N = \g_@@_kernel_bool ,
+    stdmodule .bool_gset_inverse:N = \g_@@_kernel_bool ,
+    lm-default .bool_gset:N = \g_@@_lmodern_bool ,
+    cs-break .bool_gset_inverse:N = \g_@@_cs_break_bool ,
+    cs-break-nohyphen .code:n = \PassOptionsToPackage{nohyphen}{underscore} ,
+    show-notes .bool_gset:N = \g_@@_show_notes_bool,
+    hide-notes .bool_gset_inverse:N = \g_@@_show_notes_bool
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\DeclareUnknownKeyHandler [ l3doc / options ]
+  { \PassOptionsToClass { \CurrentOption } { article } }
+\SetKeys [ l3doc / options ]
+  { full , check = false , checktest = false , lm-default }
+\PassOptionsToClass { a4paper } { article }
+%    \end{macrocode}
+%
+% Input a local configuration file, if it exists, with a message to the
+% console that this has happened. Since we distribute a \file{.cfg} file
+% with the class, this should usually always be true. Therefore, check
+% for \cs{ExplMakeTitle} (defined in \enquote{our} \file{.cfg} file) and
+% only output the informational message if it's not found.
+%
+%    \begin{macrocode}
+\msg_new:nnn { l3doc } { input-cfg }
+  { Local~config~file~l3doc.cfg~loaded. }
+\file_if_exist:nT { l3doc.cfg }
+  {
+    \file_input:n { l3doc.cfg }
+    \cs_if_exist:cF { ExplMakeTitle }
+      { \msg_info:nn { l3doc } { input-cfg } }
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\ProcessKeyOptions [ l3doc / options ]
+%    \end{macrocode}
+%
+%
+% \subsection{Class and package loading}
+%
+%    \begin{macrocode}
+\LoadClass{article}
+\RequirePackage{doc}
+\RequirePackage
+  {
+    array,
+    alphalph,
+    amsmath,
+    amssymb,
+    booktabs,
+    color,
+    colortbl,
+    hologo,
+    enumitem,
+    pifont,
+    textcomp,
+    trace,
+    csquotes,
+    fancyvrb,
+    underscore,
+    verbatim
+  }
+\raggedbottom
+%    \end{macrocode}
+%
+% Depending on the option, load the package \pkg{lmodern} to set the
+% font.  Then replace the italic typewriter font with the oblique shape
+% instead; the former makes my skin crawl. (Will, Aug 2011)
+%    \begin{macrocode}
+\bool_if:NT \g_@@_lmodern_bool
+  {
+    \RequirePackage[T1]{fontenc}
+    \RequirePackage{lmodern}
+    \group_begin:
+      \ttfamily
+      \DeclareFontShape{T1}{lmtt}{m}{it}{<->ec-lmtto10}{}
+    \group_end:
+  }
+%    \end{macrocode}
+%
+% Must be last, as usual.
+%    \begin{macrocode}
+\RequirePackage{hypdoc}
+%    \end{macrocode}
+%
+% \subsection{Configuration and tweaks}
+%
+% \begin{macro}{\MakePrivateLetters}
+%   A few more letters are \enquote{private} in a \LaTeX3 programming
+%   environment.
+%    \begin{macrocode}
+\cs_gset:Npn \MakePrivateLetters
+  {
+    \char_set_catcode_letter:N \@
+    \char_set_catcode_letter:N \_
+    \char_set_catcode_letter:N \:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{CodelineNo}
+%   Some configurations which have to do with line numbering.
+%    \begin{macrocode}
+\setcounter{StandardModuleDepth}{1}
+\@addtoreset{CodelineNo}{part}
+\tl_replace_once:Nnn \theCodelineNo
+  { \HDorg at theCodelineNo }
+  { \textcolor[gray]{0.5} { \sffamily\tiny\arabic{CodelineNo} } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\verbatim, \endverbatim}
+%   In \file{.dtx} documents, the \env{verbatim} environment adds extra
+%   space because it only removes the first \enquote{\%} sign, and not
+%   the indentation (typically a space).  Fix it with \pkg{fancyvrb}:
+%    \begin{macrocode}
+\fvset{gobble=2}
+\cs_gset_eq:NN \verbatim \Verbatim
+\cs_gset_eq:NN \endverbatim \endVerbatim
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ifnot at excluded}
+%   This function tests whether a macro name stored in
+%   \tn{macro at namepart} was excluded from indexing by \tn{DoNotIndex}.
+%   Rather than trying to fix catcodes that come into here, turn
+%   everything to string catcodes.  This is slightly inefficient as we
+%   could have ensured that \tn{index at excludelist} has string catcodes
+%   in the first place.
+%    \begin{macrocode}
+\cs_set_protected:Npn \ifnot at excluded
+  {
+    \exp_args:Nee \expanded at notin
+      { \c_backslash_str \tl_to_str:N \macro at namepart , }
+      { \exp_args:NV \tl_to_str:n \index at excludelist }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfstringnewline}
+% \begin{macro}{\@@_pdfstring_newline:w}
+%   We avoid some hyperref warnings by making |\\| (almost) trivial in
+%   bookmarks: more precisely it might be used with a star and an
+%   optional argument, which we thus remove using an \pkg{ltcmd}
+%   expandable command.  Since there cannot be trailing optional
+%   arguments, pick up an extra mandatory one and put it back.
+%    \begin{macrocode}
+\cs_new:Npn \pdfstringnewline { : ~ }
+\DeclareExpandableDocumentCommand
+  { \@@_pdfstring_newline:w } { s o m } { \pdfstringnewline #3 }
+\pdfstringdefDisableCommands
+  { \cs_set_eq:NN \\ \@@_pdfstring_newline:w }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Design}
+%
+% Increase the text width slightly so that width the standard fonts
+% 72~columns of code may appear in a \env{macrocode} environment.
+% Increase the marginpar width slightly, for long command names.  And
+% increase the left margin by a similar amount.
+%    \begin{macrocode}
+\setlength   \textwidth      { 385pt }
+\addtolength \marginparwidth {  30pt }
+\addtolength \oddsidemargin  {  20pt }
+\addtolength \evensidemargin {  20pt }
+%    \end{macrocode}
+% (These were introduced when \cls{article} was the documentclass, but
+% I've left them here for now to remind me to do something about them
+% later.)
+%
+% \begin{macro}{\list}
+% \begin{macro}{\@@_oldlist:nn}
+%   Customise lists.
+%    \begin{macrocode}
+\cs_new_eq:NN \@@_oldlist:nn \list
+\cs_gset:Npn \list #1 #2
+  { \@@_oldlist:nn {#1} { #2 \dim_zero:N \listparindent } }
+\setlength \parindent  { 2em }
+\setlength \itemindent { 0pt }
+\setlength \parskip    { 0pt plus 3pt minus 0pt }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\partname}
+%   Use \enquote{File} as a name in Part titles.
+%    \begin{macrocode}
+\tl_gset:Nn \partname {File}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l at section, \l at subsection}
+%   Customise the table of contents (as we have so many sections).
+%   Different design and/or structure is called for.
+%    \begin{macrocode}
+\@addtoreset{section}{part}
+\cs_gset:Npn \l at section #1#2
+  {
+    \ifnum \c at tocdepth >\z@
+      \addpenalty\@secpenalty
+      \addvspace{1.0em \@plus\p@}
+      \setlength\@tempdima{2.5em}  % was 1.5em
+      \begingroup
+        \parindent \z@ \rightskip \@pnumwidth
+        \parfillskip -\@pnumwidth
+        \leavevmode \bfseries
+        \advance\leftskip\@tempdima
+        \hskip -\leftskip
+        #1\nobreak\hfil \nobreak\hb at xt@\@pnumwidth{\hss #2}\par
+      \endgroup
+    \fi
+  }
+\cs_gset:Npn \l at subsection
+  { \@dottedtocline{2}{2.5em}{2.3em} }  % #2 = 1.5em
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Text markup}
+%
+% Make "|" and |"| be \enquote{short verb} characters, but not in the
+% document preamble, where an active character may interfere with
+% packages that are loaded.  Remove these short-hands at the end of the
+% document before reading the \file{.aux} file, as they may appear in
+% labels (for instance, \pkg{l3fp} documents an operation "||").
+%    \begin{macrocode}
+\AtBeginDocument
+  {
+    \MakeShortVerb \"
+    \MakeShortVerb \|
+  }
+\AtEndDocument
+  {
+    \DeleteShortVerb \"
+    \DeleteShortVerb \|
+  }
+%    \end{macrocode}
+%
+% \begin{macro}{\eTeX, \IniTeX, \Lua, \LuaTeX, \pdfTeX, \XeTeX,
+%   \pTeX, \upTeX, \epTeX, \eupTeX}
+%   Some commands for logos.
+%    \begin{macrocode}
+\providecommand*\eTeX{\hologo{eTeX}}
+\providecommand*\IniTeX{\hologo{iniTeX}}
+\providecommand*\Lua{Lua}
+\providecommand*\LuaTeX{\hologo{LuaTeX}}
+\providecommand*\pdfTeX{\hologo{pdfTeX}}
+\providecommand*\XeTeX{\hologo{XeTeX}}
+\providecommand*\pTeX{p\kern-.2em\hologo{TeX}}
+\providecommand*\upTeX{up\kern-.2em\hologo{TeX}}
+\providecommand*\epTeX{$\varepsilon$-\pTeX}
+\providecommand*\eupTeX{$\varepsilon$-\upTeX}
+\providecommand*\ConTeXt{\hologo{ConTeXt}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\cmd, \cs, \tn}
+%   They rely on a common auxiliary \cs{@@_cmd:nn} which receives as
+%   arguments the options and some tokens whose string representation
+%   starts with a backslash (to support cases such as |\cs{pkg_\ldots}|,
+%   we do not turn the whole argument into a string).
+%    \begin{macrocode}
+\DeclareDocumentCommand \cmd { O{} m }
+  { \@@_cmd:no {#1} { \token_to_str:N #2 } }
+\DeclareDocumentCommand \cs  { O{} m }
+  { \@@_cmd:no {#1} { \c_backslash_str #2 } }
+\DeclareDocumentCommand \tn  { O{} m }
+  {
+    \@@_cmd:no
+      { module = TeX , replace = false , #1 }
+      { \c_backslash_str #2 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\meta}
+%   A document-level command.
+%    \begin{macrocode}
+\DeclareDocumentCommand \meta { m }
+  { \texttt{ \@@_meta:n {#1} } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+%   {
+%     \@@_pdfstring_cmd:w,
+%     \@@_pdfstring_cs:w,
+%     \@@_pdfstring_meta:w
+%   }
+%   To work within a bookmark, these commands must be expandable.
+%    \begin{macrocode}
+\DeclareExpandableDocumentCommand
+  { \@@_pdfstring_cmd:w } { o m } { \token_to_str:N #2 }
+\DeclareExpandableDocumentCommand
+  { \@@_pdfstring_cs:w }  { o m } { \textbackslash \tl_to_str:n {#2} }
+\cs_new:Npn \@@_pdfstring_meta:w #1
+  { < \tl_to_str:n {#1} > }
+\pdfstringdefDisableCommands
+  {
+    \cs_set_eq:NN \cmd       \@@_pdfstring_cmd:w
+    \cs_set_eq:NN \cs        \@@_pdfstring_cs:w
+    \cs_set_eq:NN \tn        \@@_pdfstring_cs:w
+    \cs_set_eq:NN \meta      \@@_pdfstring_meta:w
+    \cs_set_eq:NN \@@_meta:n \@@_pdfstring_meta:w
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\Arg, \marg, \oarg, \parg}
+%   |\marg{text}| prints \marg{text}, \enquote{mandatory argument}.\\
+%   |\oarg{text}| prints \oarg{text}, \enquote{optional argument}.\\
+%   |\parg{te,xt}| prints \parg{te,xt}, \enquote{picture mode argument}.
+%   Finally, \cs{Arg} is the same as \cs{marg}.
+%    \begin{macrocode}
+\newcommand\Arg[1]
+  { \texttt{\char`\{} \@@_meta:n {#1} \texttt{\char`\}} }
+\providecommand\marg[1]{ \Arg{#1} }
+\providecommand\oarg[1]{ \texttt[ \@@_meta:n {#1} \texttt] }
+\providecommand\parg[1]{ \texttt( \@@_meta:n {#1} \texttt) }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\file, \env, \pkg, \cls}
+%   This list may change\dots this is just my preference for markup.
+%    \begin{macrocode}
+\DeclareRobustCommand \file {\nolinkurl}
+\DeclareRobustCommand \env {\texttt}
+\DeclareRobustCommand \pkg {\textsf}
+\DeclareRobustCommand \cls {\textsf}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\EnableDocumentation, \EnableImplementation}
+% \begin{macro}{\DisableDocumentation, \DisableImplementation}
+%   Control whether to typeset the documentation/implementation or not.
+%   These simply set two switches.
+%    \begin{macrocode}
+\NewDocumentCommand \EnableDocumentation { }
+  { \bool_gset_true:N \g_@@_typeset_documentation_bool }
+\NewDocumentCommand \EnableImplementation { }
+  { \bool_gset_true:N \g_@@_typeset_implementation_bool }
+\NewDocumentCommand \DisableDocumentation { }
+  { \bool_gset_false:N \g_@@_typeset_documentation_bool }
+\NewDocumentCommand \DisableImplementation { }
+  { \bool_gset_false:N \g_@@_typeset_implementation_bool }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{environment}{documentation}
+% \begin{environment}{implementation}
+%   If the documentation/implementation should be typeset, then simply
+%   set the boolean \cs{l_@@_in_implementation_bool} which indicates
+%   whether we are within the implementation section.  Otherwise use
+%   \cs{comment} (and a paired \cs{endcomment}).
+%    \begin{macrocode}
+\NewDocumentEnvironment { documentation } { }
+  {
+    \bool_if:NTF \g_@@_typeset_documentation_bool
+      { \bool_set_false:N \l_@@_in_implementation_bool }
+      { \comment }
+  }
+  { \bool_if:NF \g_@@_typeset_documentation_bool { \endcomment } }
+\NewDocumentEnvironment { implementation } { }
+  {
+    \bool_if:NTF \g_@@_typeset_implementation_bool
+      { \bool_set_true:N \l_@@_in_implementation_bool }
+      { \comment }
+  }
+  { \bool_if:NF \g_@@_typeset_implementation_bool { \endcomment } }
+%    \end{macrocode}
+% \end{environment}
+% \end{environment}
+%
+% \begin{environment}{variable}
+%   The \env{variable} environment behaves as a \env{function} or
+%   \env{macro} environment depending on the part of the document.
+%    \begin{macrocode}
+\DeclareDocumentEnvironment { variable } { O{} +v }
+  {
+    \bool_if:NTF \l_@@_in_implementation_bool
+      { \@@_macro:nnw { var , #1 } {#2} }
+      { \@@_function:nnw {#1} {#2} }
+  }
+  {
+    \bool_if:NTF \l_@@_in_implementation_bool
+      { \@@_macro_end: }
+      { \@@_function_end: }
+  }
+%    \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{function}
+% \begin{environment}{macro}
+%   Environment for documenting function(s), and environment for
+%   documenting the implementation of a macro.
+%    \begin{macrocode}
+\DeclareDocumentEnvironment { function } { O{} +v }
+  { \@@_function:nnw {#1} {#2} }
+  { \@@_function_end: }
+\DeclareDocumentEnvironment { macro } { O{} +v }
+  { \@@_macro:nnw {#1} {#2} }
+  { \@@_macro_end: }
+%    \end{macrocode}
+% \end{environment}
+% \end{environment}
+%
+% \begin{environment}{syntax}
+%   Syntax block placed next to the list of functions to illustrate
+%   their use.  TODO: test that the \env{syntax} environment is only
+%   used inside the \env{function} environment, and that it only appears
+%   once.
+%    \begin{macrocode}
+\NewDocumentEnvironment { syntax } { }
+  { \@@_syntax:w }
+  {
+    \@@_syntax_end:
+    \ignorespacesafterend
+  }
+%    \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{texnote}
+%   Used to describe information destined to \TeX{} experts only.
+%    \begin{macrocode}
+\NewDocumentEnvironment { texnote } { }
+  {
+    \endgraf
+    \vspace{3mm}
+    \small\textbf{\TeX~hackers~note:}
+  }
+  {
+    \vspace{3mm}
+  }
+%    \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{arguments}
+%   This environment is designed to be used within a \env{macro}
+%   environment to describe the arguments of the macro/function.
+%    \begin{macrocode}
+\NewDocumentEnvironment { arguments } { }
+  {
+    \enumerate [
+      nolistsep ,
+      label = \texttt{\#\arabic*} ~ : ,
+      labelsep = * ,
+    ]
+  }
+  {
+    \endenumerate
+  }
+%    \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\CodedocExplain, \CodedocExplainEXP, \CodedocExplainREXP, \CodedocExplainTF}
+%   Explanation of stars and |TF| notations, for use in third-party
+%   packages.
+%    \begin{macrocode}
+\NewDocumentCommand { \CodedocExplain } { }
+  { \CodedocExplainEXP \ \CodedocExplainREXP \ \CodedocExplainTF }
+\NewDocumentCommand { \CodedocExplainEXP } { }
+  {
+    \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{expstar}{}}%
+    \write \@auxout { \def \string \Codedoc at expstar { } }
+    \@@_typeset_exp:\ indicates~fully~expandable~functions,~which~
+    can~be~used~within~an~\texttt{e}-type~argument~(inside~an~\tn{expanded}),~
+    \texttt{x}-type~argument~(in~plain~\TeX{}~terms,~inside~an~\tn{edef}),~
+    as~well~as~within~an~\texttt{f}-type~argument.
+  }
+\NewDocumentCommand { \CodedocExplainREXP } { }
+  {
+    \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{rexpstar}{}}%
+    \write \@auxout { \def \string \Codedoc at rexpstar { } }
+    \@@_typeset_rexp:\ indicates~
+    restricted~expandable~functions,~which~can~be~used~within~an~
+    \texttt{x}-type~argument~or~an~\texttt{e}-type~argument,~
+    but~cannot~be~fully~expanded~within~an~\texttt{f}-type~argument.
+  }
+\NewDocumentCommand { \CodedocExplainTF } { }
+  {
+    \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{explTF}{}}%
+    \write \@auxout { \def \string \Codedoc at explTF { } }
+    \@@_typeset_TF:\ indicates~conditional~(\texttt{if})~functions~
+    whose~variants~with~\texttt{T},~\texttt{F}~and~\texttt{TF}~
+    argument~specifiers~expect~different~
+    \enquote{true}/\enquote{false}~branches.
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Implementing text markup}
+%
+% Keys for \cs{cmd}, \cs{cs} and \cs{tn}.
+%    \begin{macrocode}
+\keys_define:nn { l3doc/cmd }
+  {
+    index     .tl_set:N     = \l_@@_cmd_index_tl        ,
+    module    .tl_set:N     = \l_@@_cmd_module_tl       ,
+    no-index  .bool_set:N   = \l_@@_cmd_noindex_bool    ,
+    replace   .bool_set:N   = \l_@@_cmd_replace_bool    ,
+  }
+%    \end{macrocode}
+%
+% \begin{macro}[do-not-index={\\,\_,\1,\c,\2}]{\@@_cmd:nn, \@@_cmd:no}
+%   Apply the key--value \meta{options}~|#1| after setting some
+%   default values.  Then (unless |replace=false|) replace |@@| in~|#2|,
+%   which is a bit tricky: the |_| must be given the catcode expected by
+%   \cs{@@_replace_at_at:N}, but should be reverted to their original
+%   catcode (normally active, needed for line-breaking) without
+%   rescanning the whole argument.  Then typeset the command in
+%   \tn{verbatim at font}, after turning it to harmless characters if
+%   needed (and keeping the underscore breakable); in any case, spaces
+%   must be turned into \tn{@xobeysp} and we must use \tn{@} to avoid
+%   longer spaces after a control sequence that ends for instance with a
+%   colon (empty signature).  Finally, produce an index entry.
+%   Indexing is suppressed when \cs{l_@@_cmd_noindex_bool} is true.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_cmd:nn #1#2
+  {
+    \bool_set_false:N \l_@@_cmd_noindex_bool
+    \bool_set_true:N \l_@@_cmd_replace_bool
+    \tl_set:Nn \l_@@_cmd_index_tl { \q_no_value }
+    \tl_set:Nn \l_@@_cmd_module_tl { \q_no_value }
+    \keys_set:nn { l3doc/cmd } {#1}
+    \tl_set:Nn \l_@@_cmd_tl {#2}
+    \bool_if:NT \l_@@_cmd_replace_bool
+      {
+        \tl_set_rescan:Nnn \l_@@_tmpb_tl { } { _ }
+        \tl_replace_all:NVn \l_@@_cmd_tl \l_@@_tmpb_tl { _ }
+        \@@_replace_at_at:N \l_@@_cmd_tl
+        \tl_replace_all:NnV \l_@@_cmd_tl { _ } \l_@@_tmpb_tl
+      }
+%    \end{macrocode}
+% Typesetting.
+% Note the replacement for the underscore is to permit linebreaks.
+% The \texttt{underscore} package adds the linebreak,
+% and the regex results in applying the breakable underscore only to the \emph{last}
+% of a run of underscores, and not if the underscore follows a backslash.
+%    \begin{macrocode}

@@ Diff output truncated at 1234567 characters. @@


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