diff options
author | Karl Berry <karl@freefriends.org> | 2017-05-14 22:40:58 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2017-05-14 22:40:58 +0000 |
commit | e0c5d6d38a1f285f20a66692e46d2e607d6ff1dd (patch) | |
tree | 977232bc088d27b46d9a6330c8f4f47aa98dbb78 /Master/texmf-dist | |
parent | 4407d96af752e6e79a48c25c5189bd1a63fbd125 (diff) |
l3 (14may17)
git-svn-id: svn://tug.org/texlive/trunk@44351 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
158 files changed, 4412 insertions, 3264 deletions
diff --git a/Master/texmf-dist/doc/latex/l3build/README.md b/Master/texmf-dist/doc/latex/l3build/README.md index 12347ef5e6c..f660f40af9b 100644 --- a/Master/texmf-dist/doc/latex/l3build/README.md +++ b/Master/texmf-dist/doc/latex/l3build/README.md @@ -1,7 +1,7 @@ l3build: a testing and building system for LaTeX3 ================================================= -Release 2017/04/01 +Release 2017/05/13 Overview -------- diff --git a/Master/texmf-dist/doc/latex/l3build/l3build.pdf b/Master/texmf-dist/doc/latex/l3build/l3build.pdf Binary files differindex e6060d9c47d..377180129c5 100644 --- a/Master/texmf-dist/doc/latex/l3build/l3build.pdf +++ b/Master/texmf-dist/doc/latex/l3build/l3build.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/README.md b/Master/texmf-dist/doc/latex/l3experimental/README.md index 69f9947a0fd..a4fcc33bde8 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/README.md +++ b/Master/texmf-dist/doc/latex/l3experimental/README.md @@ -1,7 +1,7 @@ Experimental LaTeX3 Concepts ============================ -Release 2017/04/01 +Release 2017/05/13 Overview -------- diff --git a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3intarray.pdf b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3intarray.pdf Binary files differnew file mode 100644 index 00000000000..d636674bc80 --- /dev/null +++ b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3intarray.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdf b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdf Binary files differindex fe92a8a4207..01cfbdbb127 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdf +++ b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3regex.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-convert.pdf b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-convert.pdf Binary files differindex 5c3f33f7eac..187de639968 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-convert.pdf +++ b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-convert.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-format.pdf b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-format.pdf Binary files differindex c5a0da66877..9c72c830baf 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-format.pdf +++ b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-format.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3tl-analysis.pdf b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3tl-analysis.pdf Binary files differindex d0748e9f0c5..b7035acda05 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3tl-analysis.pdf +++ b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3tl-analysis.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3tl-build.pdf b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3tl-build.pdf Binary files differindex 6838ba79b7a..50c18f66a91 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/l3str/l3tl-build.pdf +++ b/Master/texmf-dist/doc/latex/l3experimental/l3str/l3tl-build.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf b/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf Binary files differindex 903955aef71..59d76b7dd49 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf +++ b/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf b/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf Binary files differindex 6621992f911..8859730fe8d 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf +++ b/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf diff --git a/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf b/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf Binary files differindex 6a32cc43b7f..9768984fbe5 100644 --- a/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf +++ b/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/README.md b/Master/texmf-dist/doc/latex/l3kernel/README.md index e83a0008220..ec32d80e731 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/README.md +++ b/Master/texmf-dist/doc/latex/l3kernel/README.md @@ -1,7 +1,7 @@ LaTeX3 Programming Conventions ============================== -Release 2017/04/01 +Release 2017/05/13 Overview -------- diff --git a/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf b/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf Binary files differindex 26f49c55b60..27bba9740e1 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf b/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf Binary files differindex 992bb3ef621..3647b2b48f2 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf Binary files differindex edcbc5a1c83..8bc6bf4fada 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3obsolete.txt b/Master/texmf-dist/doc/latex/l3kernel/l3obsolete.txt index 07881c1136b..5d8e254af51 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3obsolete.txt +++ b/Master/texmf-dist/doc/latex/l3kernel/l3obsolete.txt @@ -16,7 +16,8 @@ They will be removed from the sources at the end of the given year. Function Expires end -------------------------------------- \c_minus_one 2018 -\GetIdInfo 2018 +\box_resize:cnn 2018 +\box_resize:Nnn 2018 \ior_get_str:NN 2017 \sort_ordered: 2018 \sort_reversed: 2018 diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf Binary files differindex 33044d009fb..25a4ac803ea 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex index 9300d716d8e..909461fe12f 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex +++ b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex @@ -30,7 +30,7 @@ The released version of this bundle is available from CTAN. {latex-team@latex-project.org}% }% } -\date{Released 2017/04/01} +\date{Released 2017/05/13} \begin{document} diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf Binary files differindex 4ea492eebd5..60a0c7a2d4c 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex index a98aa1f51a4..5e39806bda2 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex +++ b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex @@ -30,7 +30,7 @@ The released version of this bundle is available from CTAN. {latex-team@latex-project.org}% }% } -\date{Released 2017/04/01} +\date{Released 2017/05/13} \newcommand{\TF}{\textit{(TF)}} diff --git a/Master/texmf-dist/doc/latex/l3kernel/source3.pdf b/Master/texmf-dist/doc/latex/l3kernel/source3.pdf Binary files differindex 8bc231baa9b..a0f086afe40 100644 --- a/Master/texmf-dist/doc/latex/l3kernel/source3.pdf +++ b/Master/texmf-dist/doc/latex/l3kernel/source3.pdf diff --git a/Master/texmf-dist/doc/latex/l3packages/README.md b/Master/texmf-dist/doc/latex/l3packages/README.md index 0d9e60ef831..9fb0ae2bb43 100644 --- a/Master/texmf-dist/doc/latex/l3packages/README.md +++ b/Master/texmf-dist/doc/latex/l3packages/README.md @@ -1,7 +1,7 @@ LaTeX3 High-Level Concepts ========================== -Release 2017/04/01 +Release 2017/05/13 Overview -------- diff --git a/Master/texmf-dist/doc/latex/l3packages/l3keys2e/l3keys2e.pdf b/Master/texmf-dist/doc/latex/l3packages/l3keys2e/l3keys2e.pdf Binary files differindex fa6542d3d33..acd5b6d2d77 100644 --- a/Master/texmf-dist/doc/latex/l3packages/l3keys2e/l3keys2e.pdf +++ b/Master/texmf-dist/doc/latex/l3packages/l3keys2e/l3keys2e.pdf diff --git a/Master/texmf-dist/doc/latex/l3packages/xfp/xfp.pdf b/Master/texmf-dist/doc/latex/l3packages/xfp/xfp.pdf Binary files differindex a62cdf3f3c7..165ec365d4d 100644 --- a/Master/texmf-dist/doc/latex/l3packages/xfp/xfp.pdf +++ b/Master/texmf-dist/doc/latex/l3packages/xfp/xfp.pdf diff --git a/Master/texmf-dist/doc/latex/l3packages/xfrac/xfrac.pdf b/Master/texmf-dist/doc/latex/l3packages/xfrac/xfrac.pdf Binary files differindex 7d0c18179ef..d25a5fb1de9 100644 --- a/Master/texmf-dist/doc/latex/l3packages/xfrac/xfrac.pdf +++ b/Master/texmf-dist/doc/latex/l3packages/xfrac/xfrac.pdf diff --git a/Master/texmf-dist/doc/latex/l3packages/xparse/xparse.pdf b/Master/texmf-dist/doc/latex/l3packages/xparse/xparse.pdf Binary files differindex 4499c615633..2eedc21e4e5 100644 --- a/Master/texmf-dist/doc/latex/l3packages/xparse/xparse.pdf +++ b/Master/texmf-dist/doc/latex/l3packages/xparse/xparse.pdf diff --git a/Master/texmf-dist/doc/latex/l3packages/xtemplate/xtemplate.pdf b/Master/texmf-dist/doc/latex/l3packages/xtemplate/xtemplate.pdf Binary files differindex 031f0e8779b..ddd3231aadc 100644 --- a/Master/texmf-dist/doc/latex/l3packages/xtemplate/xtemplate.pdf +++ b/Master/texmf-dist/doc/latex/l3packages/xtemplate/xtemplate.pdf diff --git a/Master/texmf-dist/source/latex/l3build/l3build.dtx b/Master/texmf-dist/source/latex/l3build/l3build.dtx index 7287b1a9ac1..81665872e6f 100644 --- a/Master/texmf-dist/source/latex/l3build/l3build.dtx +++ b/Master/texmf-dist/source/latex/l3build/l3build.dtx @@ -201,7 +201,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % \tableofcontents @@ -1026,8 +1026,7 @@ % a suitable function might read as shown in Figure~\ref{fig:update-line}. % \begin{figure} % \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6] -% function setversion_update_line(line, date, version) -% local i +% function setversion_update_line(line, date, release) % -- No real regex so do it one type at a time % for _,i in pairs({"Class", "File", "Package"}) do % if string.match( @@ -1037,7 +1036,7 @@ % line = string.gsub(line, "%[%d%d%d%d/%d%d/%d%d", "[" % .. string.gsub(date, "%-", "/") % line = string.gsub( -% line, "(%[%d%d%d%d/%d%d/%d%d) [^ ]*", "%1 " .. version +% line, "(%[%d%d%d%d/%d%d/%d%d) [^ ]*", "%1 " .. release % ) % break % end @@ -1105,6 +1104,177 @@ % \label{fig:PDF} % \end{figure} % +% \section{Lua interfaces} +% +% Whilst for the majority of users the simple variable-based control methods +% outlined above will suffice, for more advanced applications there will be +% a need to adjust behavior by using interfaces within the Lua code. This +% section details the global variables and functions provided. +% +% \subsection{Global variables} +% +% \begin{variable}{options} +% The |options| table holds the values passed to \pkg{l3build} at the +% command line. The possible entries in the table are given in the table +% below. +% \begin{center} +% \begin{tabular}{ll} +% \toprule +% Entry & Type \\ +% \midrule +% \var{date} & String \\ +% \var{engine} & Table \\ +% \var{files} & Table \\ +% \var{halt} & Boolean \\ +% \var{help} & Boolean \\ +% \var{pdf} & Boolean \\ +% \var{quiet} & Boolean \\ +% \var{release} & String \\ +% \var{testfiledir} & String \\ +% \bottomrule +% \end{tabular} +% \end{center} +% \end{variable} +% +% \subsection{Utility functions} +% +% The utility functions are largely focussed on file operations, though a small +% number of others are provided. File paths should be given in Unix style +% (using |/| as a path separator). File operations take place relative to the +% path from which \pkg{l3build} is called. File operation syntax is largely +% modelled on Unix command line commands but reflect the need to work on +% Windows in a flexible way. +% +% \begin{function}{abspath()} +% \begin{syntax} +% |abspath(|\meta{target}|)| +% \end{syntax} +% Returns a string which gives the absolute location of the +% \meta{target} directory. +% \end{function} +% +% \begin{function}{cleandir()} +% \begin{syntax} +% |cleandir(|\meta{dir}|)| +% \end{syntax} +% Removes any content within the \meta{dir}; returns an error level. +% \end{function} +% +% \begin{function}{cp()} +% \begin{syntax} +% |cp(|\meta{glob}, \meta{source}, \meta{destination}|)| +% \end{syntax} +% Copies files matching the \meta{glob} from the \meta{source} directory +% to the \meta{destination}; returns an error level. +% \end{function} +% +% \begin{function}{direxists()} +% \begin{syntax} +% |direxists(|\meta{dir}|)| +% \end{syntax} +% Tests if the \meta{dir} exists; returns a boolean value. +% \end{function} +% +% \begin{function}{fileexists()} +% \begin{syntax} +% |fileexists(|\meta{file}|)| +% \end{syntax} +% Tests if the \meta{file} exists; returns a boolean value. +% \end{function} +% +% \begin{function}{filelist()} +% \begin{syntax} +% |filelist(|\meta{path}, \oarg{glob}|)| +% \end{syntax} +% Returns a table containing all of the files with the \meta{path} +% which match the \meta{glob}; if the latter is absent returns a list of +% all files in the \meta{path}. +% \end{function} +% +% \begin{function}{mkidr()} +% \begin{syntax} +% |mkdir(|\meta{dir}|)| +% \end{syntax} +% Creates the \meta{dir}; returns an error level. +% \end{function} +% +% \begin{function}{ren()} +% \begin{syntax} +% |ren(|\meta{dir}, \meta{source}, \meta{destination}|)| +% \end{syntax} +% Renames the \meta{source} file to the \meta{destination} name within +% the \meta{dir}; returns an error level. +% \end{function} +% +% \begin{function}{rm()} +% \begin{syntax} +% |rm(|\meta{dir}, \meta{glob}|)| +% \end{syntax} +% Removes files in the \meta{dir} matching the \meta{glob}; returns an +% error level. +% \end{function} +% +% \begin{function}{run()} +% \begin{syntax} +% |run(|\meta{dir}, \meta{cmd}|)| +% \end{syntax} +% Executes the \meta{cmd}, starting it in the \meta{dir}; returns an +% error level. +% \end{function} +% +% \begin{function}{unix_to_win()} +% \begin{syntax} +% |unix_to_win(|\meta{path}|)| +% \end{syntax} +% Returns a string comprising the \meta{path} with |/| characters replaced +% by |\\| and thus suitable for use with Windows-specific commands which +% require this form of path. +% \end{function} +% +% \subsection{System-dependent strings} +% +% To support creation of additional functionality, the following low-level +% strings are exposed by \pkg{l3build}: these all have system-dependent +% definitions and avoid the need to test |os.type| during the construction +% of system calls. +% +% \begin{variable}{os_concat} +% The concatenation operation for using multiple commands in one +% system call, \emph{e.g.} +% \begin{verbatim} +% os.execute("tex " .. file .. os_concat .. "tex " .. file) +% \end{verbatim} +% \end{variable} +% +% \begin{variable}{os_null} +% The location to redirect commands which should produce no output +% at the terminal: almost always used preded by |>|, \emph{e.g.} +% \begin{verbatim} +% os.execute("tex " .. file .. " > " .. os_null) +% \end{verbatim} +% \end{variable} +% +% \begin{variable}{os_pathsep} +% The separator used when setting an environment variable to multiple +% paths, \emph{e.g.} +% \begin{verbatim} +% os.execute(os_setenv .. " PATH=../a" .. os_pathsep .. "../b") +% \end{verbatim} +% \end{variable} +% +% \begin{variable}{os_setenv} +% The command to set an environmental variable, \emph{e.g.} +% \begin{verbatim} +% os.execute(os_setenv .. " PATH=../a") +% \end{verbatim} +% \end{variable} +% +% \begin{variable}{os_yes} +% A command to generate a series of $200$ lines each containing the +% character |y|: this is useful as the Unix |yes| command cannot be +% used inside |os.execute| (it does not terminate). +% \end{variable} +% % \end{documentation} % % \begin{implementation} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx new file mode 100644 index 00000000000..0327082bf18 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3intarray.dtx @@ -0,0 +1,271 @@ +% \iffalse meta-comment +% +%% File: l3intarray.dtx Copyright (C) 2017 The LaTeX3 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 "l3experimental 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|package> +% The version of expl3 required is tested as early as possible, as +% some really old versions do not define \ProvidesExplPackage. +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} +%<package> {} +%<package> {% +%<package> \PackageError{l3intarray}{Support package l3kernel too old} +%<package> {% +%<package> Please install an up to date version of l3kernel\MessageBreak +%<package> using your TeX package manager or from CTAN.\MessageBreak +%<package> \MessageBreak +%<package> Loading l3intarray will abort!% +%<package> }% +%<package> \endinput +%<package> } +%</driver|package> +%<*driver> +\documentclass[full]{l3doc} +\usepackage{amsmath} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% +% \title{^^A +% The \textsf{l3intarray} package: low-level arrays of small integers^^A +% } +% +% \author{^^A +% The \LaTeX3 Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released 2017/05/13} +% +% \maketitle +% +% \begin{documentation} +% +% \section{\pkg{l3intarray} documentation} +% +% This module provides no user function: at present it is meant for +% kernel use only. +% +% It is a wrapper around the \tn{fontdimen} primitive, used to store +% arrays of integers (with a restricted range: absolute value at most +% $2^{30}-1$). In contrast to \pkg{l3seq} sequences the access to +% individual entries is done in constant time rather than linear time, +% but only integers can be stored. More precisely, the primitive +% \tn{fontdimen} stores dimensions but the \pkg{l3intarray} package +% transparently converts these from/to integers. Assignments are always +% global. +% +% While \LuaTeX{}'s memory is extensible, other engines can +% \enquote{only} deal with a bit less than $4\times 10^6$ entries in all +% \tn{fontdimen} arrays combined (with default \TeX{}Live settings). +% +% \subsection{Internal functions} +% +% \begin{function}{\__intarray_new:Nn} +% \begin{syntax} +% \cs{__intarray_new:Nn} \meta{intarray~var} \Arg{size} +% \end{syntax} +% Evaluates the integer expression \meta{size} and allocates an +% \meta{integer array variable} with that number of (zero) entries. +% \end{function} +% +% \begin{function}[EXP]{\__intarray_count:N} +% \begin{syntax} +% \cs{__intarray_count:N} \meta{intarray~var} +% \end{syntax} +% Expands to the number of entries in the \meta{integer array variable}. +% Contrarily to \cs{seq_count:N} this is performed in constant time. +% \end{function} +% +% \begin{function}{\__intarray_gset:Nnn, \__intarray_gset_fast:Nnn} +% \begin{syntax} +% \cs{__intarray_gset:Nnn} \meta{intarray~var} \Arg{position} \Arg{value} +% \cs{__intarray_gset_fast:Nnn} \meta{intarray~var} \Arg{position} \Arg{value} +% \end{syntax} +% Stores the result of evaluating the integer expression \meta{value} +% into the \meta{integer array variable} at the (integer expression) +% \meta{position}. While \cs{__intarray_gset:Nnn} checks that the +% \meta{position} is between $1$ and the \cs{__intarray_count:N} and that +% the \meta{value}'s absolute value is at most $2^{30}-1$, the +% \enquote{fast} function performs no such bound check. +% Assignments are always global. +% \end{function} +% +% \begin{function}[EXP]{\__intarray_item:Nn, \__intarray_item_fast:Nn} +% \begin{syntax} +% \cs{__intarray_item:Nn} \meta{intarray~var} \Arg{position} +% \cs{__intarray_item_fast:Nn} \meta{intarray~var} \Arg{position} +% \end{syntax} +% Expands to the integer entry stored at the (integer expression) +% \meta{position} in the \meta{integer array variable}. While +% \cs{__intarray_item:Nn} checks that the \meta{position} is between $1$ +% and the \cs{__intarray_count:N}, the \enquote{fast} function performs +% no such bound check. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3intarray} implementation} +% +% \begin{macrocode} +%<*initex|package> +% \end{macrocode} +% +% \begin{macrocode} +%<@@=intarray> +% \end{macrocode} +% +% \begin{macrocode} +\ProvidesExplPackage{l3intarray}{2017/05/13}{} + {L3 Experimental low-level arrays of small integers} +% \end{macrocode} +% +% \subsection{Allocating arrays} +% +% \begin{variable}{\g_@@_font_int} +% Used to assign one font per array. +% \begin{macrocode} +\int_new:N \g_@@_font_int +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[int]{\@@_new:Nn} +% Declare |#1| to be a font (arbitrarily |cmr10| at a never-used +% size). Store the array's size as the \tn{hyphenchar} of that font +% and make sure enough \tn{fontdimen} are allocated, by setting the +% last one. Then clear any \tn{fontdimen} that |cmr10| starts with. +% It seems \LuaTeX{}'s |cmr10| has an extra \tn{fontdimen} parameter +% number $8$ compared to other engines (for a math font we would +% replace $8$ by $22$ or some such). +% \begin{macrocode} +\cs_new_protected:Npn \@@_new:Nn #1#2 + { + \__chk_if_free_cs:N #1 + \int_gincr:N \g_@@_font_int + \tex_global:D \tex_font:D #1 = cmr10~at~ \g_@@_font_int sp \scan_stop: + \tex_hyphenchar:D #1 = \int_eval:n {#2} \scan_stop: + \int_compare:nNnT { \tex_hyphenchar:D #1 } > 0 + { \tex_fontdimen:D \tex_hyphenchar:D #1 #1 = 0 sp \scan_stop: } + \int_step_inline:nnnn { 1 } { 1 } { 8 } + { \tex_fontdimen:D ##1 #1 = 0 sp \scan_stop: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int, EXP]{\@@_count:N} +% Size of an array. +% \begin{macrocode} +\cs_new:Npn \@@_count:N #1 { \tex_the:D \tex_hyphenchar:D #1 } +% \end{macrocode} +% \end{macro} +% +% \subsection{Array items} +% +% \begin{macro}[int]{\@@_gset:Nnn, \@@_gset_fast:Nnn} +% \begin{macro}[aux]{\@@_gset_aux:Nnn} +% Set the appropriate \tn{fontdimen}. The slow version checks the +% position and value are within bounds. +% \begin{macrocode} +\cs_new_protected:Npn \@@_gset_fast:Nnn #1#2#3 + { \tex_fontdimen:D \int_eval:n {#2} #1 = \int_eval:n {#3} sp \scan_stop: } +\cs_new_protected:Npn \@@_gset:Nnn #1#2#3 + { + \exp_args:Nff \@@_gset_aux:Nnn #1 + { \int_eval:n {#2} } { \int_eval:n {#3} } + } +\cs_new_protected:Npn \@@_gset_aux:Nnn #1#2#3 + { + \int_compare:nTF { 1 <= #2 <= \@@_count:N #1 } + { + \int_compare:nTF { - \c_max_dim <= \int_abs:n {#3} <= \c_max_dim } + { \@@_gset_fast:Nnn #1 {#2} {#3} } + { + \__msg_kernel_error:nnxxxx { intarray } { overflow } + { \token_to_str:N #1 } {#2} {#3} + { \int_compare:nNnT {#3} < 0 { - } \__int_value:w \c_max_dim } + \@@_gset_fast:Nnn #1 {#2} + { \int_compare:nNnT {#3} < 0 { - } \c_max_dim } + } + } + { + \__msg_kernel_error:nnxxx { intarray } { out-of-bounds } + { \token_to_str:N #1 } {#2} { \@@_count:N #1 } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_item:Nn, \@@_item_fast:Nn} +% \begin{macro}[aux]{\@@_item_aux:Nn} +% Get the appropriate \tn{fontdimen} and perform bound checks if requested. +% \begin{macrocode} +\cs_new:Npn \@@_item_fast:Nn #1#2 + { \__int_value:w \tex_fontdimen:D \int_eval:n {#2} #1 } +\cs_new:Npn \@@_item:Nn #1#2 + { \exp_args:Nf \@@_item_aux:Nn #1 { \int_eval:n {#2} } } +\cs_new:Npn \@@_item_aux:Nn #1#2 + { + \int_compare:nTF { 1 <= #2 <= \@@_count:N #1 } + { \@@_item_fast:Nn #1 {#2} } + { + \__msg_kernel_expandable_error:nnnnn { intarray } { out-of-bounds } + { \token_to_str:N #1 } {#2} { \@@_count:N #1 } + 0 + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\__msg_kernel_new:nnnn { intarray } { overflow } + { Integers~larger~than~2^{30}-1~cannot~be~stored~in~arrays. } + { + An~attempt~was~made~to~store~#3~at~position~#2~in~the~array~'#1'.~ + The~largest~allowed~value~#4~will~be~used~instead. + } +\__msg_kernel_new:nnnn { intarray } { out-of-bounds } + { Access~to~an~entry~beyond~an~array's~bounds. } + { + An~attempt~was~made~to~access~or~store~data~at~position~#2~of~the~ + array~'#1',~but~this~array~has~entries~at~positions~from~1~to~#3. + } +% \end{macrocode} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx index 3b26d43f4e5..ddfbc79de23 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3regex.dtx @@ -23,8 +23,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/04/01] -%<package>\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} %<package> {} %<package> {% %<package> \PackageError{l3regex}{Support package l3kernel too old} @@ -59,7 +59,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -352,21 +352,37 @@ % \subsection{Syntax of the replacement text} % % Most of the features described in regular expressions do not make -% sense within the replacement text. Escaped characters are supported -% as inside regular expressions. The whole match is accessed as~|\0|, -% and the first~$9$ submatches are accessed as |\1|, \ldots{},~|\9|. -% Further submatches are accessed through |\g{|\meta{number}|}| where -% \meta{number} is any non-negative integer. If there are fewer than -% \meta{number} capturing groups, the submatch is empty. +% sense within the replacement text. Backslash introduces various +% special constructions: +% \begin{itemize} +% \item |\0| is the whole match; +% \item |\1|, |\2|, \ldots{}, |\9| or |\g{|\meta{number}|}| are the +% submatches (empty if there are fewer than \meta{number} capturing +% groups); +% \item \verb*|\ | inserts a space (spaces are ignored when not +% escaped); +% \item |\a|, |\e|, |\f|, |\n|, |\r|, |\t|, |\xhh|, |\x{hhh}| +% correspond to single characters as in regular expressions; +% \item |\c|\Arg{cs~name} inserts a control sequence; +% \item |\c|\meta{category}\meta{character} (see below); +% \item |\u|\Arg{tl~var~name} inserts the contents of the +% \meta{tl~var} (see below). +% \end{itemize} +% Characters other than backslash and space are simply inserted in the +% result (but since the replacement text is first converted to a string, +% one should also escape characters that are special for \TeX{}, for +% instance use~|\#|). Non-alphanumeric characters can always be safely +% escaped with a backslash. % % For instance, % \begin{verbatim} % \tl_set:Nn \l_my_tl { Hello,~world! } -% \regex_replace_all:nnN { ([er]?l|o) . } { \(\0\-\-\1\) } \l_my_tl +% \regex_replace_all:nnN { ([er]?l|o) . } { (\0--\1) } \l_my_tl % \end{verbatim} % results in \cs{l_my_tl} holding |H(ell--el)(o,--o) w(or--o)(ld--l)!| % -% Submatches keep the same category codes as in the original token list. +% Submatches always keep the same category codes as in the original +% token list. % The characters inserted by the replacement have category code $12$ % (other) by default, with the exception of space characters. Spaces % inserted through \verb*|\ | have category code $10$, while spaces @@ -374,21 +390,25 @@ % The escape sequence |\c| allows to insert characters % with arbitrary category codes, as well as control sequences. % \begin{l3regex-syntax} -% \item[\\cXY] Produces the character~|Y| (which can be given as an -% escape sequence such as~|\t| for tab, or |\(| or~|\)| for a -% parenthesis) with category code~|X|, which must be one of -% |CBEMTPUDSLOA|. +% \item[\\cX(\ldots{})] Produces the characters \enquote{\ldots{}} with +% category~|X|, which must be one of |CBEMTPUDSLOA| as in regular +% expressions. Parentheses are optional for a single character (which +% can be an escape sequence). This can be nested, for instance +% |\cL(Hello\cS\ world)!| % \item[\\c\Arg{text}] Produces the control sequence with csname % \meta{text}. The \meta{text} may contain references to the -% submatches |\0|, |\1|, \emph{etc.} +% submatches |\0|, |\1|, and so on, as in the example for |\u| below. % \end{l3regex-syntax} % % The escape sequence |\u|\Arg{tl~var~name} allows to insert the % contents of the token list with name \meta{tl~var~name} directly into -% the replacement, avoiding the need to escape special characters. -% Within the construction |\c|\Arg{text}, the |\u|~escape sequence only -% expands its argument once, in effect performing \cs{tl_to_str:v}. -% Submatches can be used within the argument of |\u|. For instance, +% the replacement, giving an easier control of category codes. +% Within |\c{|\ldots{}|}| and |\u{|\ldots{}|}| constructions, the |\u| +% and |\c|~escape sequences perform \cs{tl_to_str:v}, namely extract the +% value of the control sequence and turn it into a string. +% +% Matches can be used within the arguments of |\c| and |\u|. For +% instance, % \begin{verbatim} % \tl_set:Nn \l_my_one_tl { first } % \tl_set:Nn \l_my_two_tl { \emph{second} } @@ -611,7 +631,8 @@ % \item Currently, |a{\x34}| is recognized as |a{4}|. % \item Cleaner error reporting in the replacement phase. % \item Add tracing information. -% \item Detect attempts to use back-references. +% \item Detect attempts to use back-references and other +% non-implemented syntax. % \item Test for the maximum register \cs{c_max_register_int}. % \item Find out whether the fact that |\W| and friends match the % end-marker leads to bugs. Possibly update \cs{__regex_item_reverse:n}. @@ -622,23 +643,19 @@ % % Code improvements to come. % \begin{itemize} -% \item Change \tn{skip} to \tn{dimen} for the array of active -% threads, and shift the array of submatch informations so that it -% starts at \tn{skip}$0$. -% \item Optimize |\c{abc}| for matching a specific control sequence. +% \item Shift arrays so that the useful information starts at +% position~$1$. % \item Only build \c{...} once. -% \item Use \tn{skip} for the left and right state stacks when +% \item Use arrays for the left and right state stacks when % compiling a regex. % \item Should \cs{__regex_action_free_group:n} only be used for greedy % |{n,}| quantifier? (I think not.) % \item Quantifiers for |\u| and assertions. -% \item Improve digit grabbing for the |\g| escape in replacement. -% Allow arbitrary integer expressions for all those numbers? % \item When matching, keep track of an explicit stack of % \texttt{current_state} and \texttt{current_submatches}. % \item If possible, when a state is reused by the same thread, kill % other subthreads. -% \item Use \tn{dimen} registers rather than \cs{l__regex_balance_tl} +% \item Use an array rather than \cs{l__regex_balance_tl} % to build \cs{__regex_replacement_balance_one_match:n}. % \item Reduce the number of epsilon-transitions in alternatives. % \item Optimize simple strings: use less states (|abcade| should give @@ -650,8 +667,6 @@ % \item Optimize the use of \cs{int_step_...} functions. % \item Groups don't capture within regexes for csnames; optimize and % document. -% \item Decide and document what |\c{\c{...}}| should do in the -% replacement text, similar questions for |\u|. % \item Better \enquote{show} for anchors, properties, and catcode tests. % \item Does |\K| really need a new state for itself? % \item When compiling, use a boolean \texttt{in_cs} and less magic @@ -664,7 +679,6 @@ % The following features are likely to be implemented at some point % in the future. % \begin{itemize} -% \item Allow |\cL(abc)| in replacement text. % \item General look-ahead/behind assertions. % \item Regex matching on external files. % \item Conditional subpatterns with look ahead/behind: \enquote{if @@ -680,13 +694,11 @@ % This requires to manipulate a lot of data, probably using tree-boxes. % \end{itemize} % -% The following features of \textsc{pcre} or Perl will probably not be +% The following features of \textsc{pcre} or Perl may or may not be % implemented. % \begin{itemize} % \item |\ddd|, matching the character with octal code \texttt{ddd}; -% \item Callout with |(?C...)|, we cannot run arbitrary user code -% during the matching, because the regex code uses registers in an -% unsafe way; +% \item Callout with |(?C...)|; % \item Conditional subpatterns (other than with a look-ahead or % look-behind condition): this is non-regular, isn't it? % \item Named subpatterns: \TeX{} programmers have lived so far @@ -705,9 +717,7 @@ % non-backtracking algorithm, and difficult to implement. % \item Subroutine calls: this syntactic sugar is difficult to include % in a non-backtracking algorithm, in particular because the -% corresponding group should be treated as atomic. Also, we cannot -% afford to run user code within the regular expression matching, -% because of our \enquote{misuse} of registers. +% corresponding group should be treated as atomic. % \item Recursion: this is a non-regular feature. % \item Back-references: non-regular feature, this requires % backtracking, which is prohibitively slow. @@ -734,9 +744,9 @@ % % \begin{macrocode} %<*package> -\ProvidesExplPackage{l3regex}{2017/04/01}{} +\ProvidesExplPackage{l3regex}{2017/05/13}{} {L3 Experimental regular expressions} -\RequirePackage{l3tl-build, l3tl-analysis, l3str-convert} +\RequirePackage{l3tl-build, l3tl-analysis, l3intarray} %</package> % \end{macrocode} % @@ -754,7 +764,7 @@ % \item (Compiling.) Analyse the regex, finding invalid input, and % convert it to an internal representation. % \item (Building.) Convert the compiled regex to a non-deterministic -% finite automaton (\textsc{nfa}) with roughly $n$ states which +% finite automaton (\textsc{nfa}) with $O(n)$ states which % accepts precisely token lists matching that regex. % \item (Matching.) Loop through the query token list one token (one % \enquote{position}) at a time, exploring in parallel every @@ -787,46 +797,42 @@ % unique id for all the steps of the matching algorithm. % \end{itemize} % -% To achieve a good performance, we abuse \TeX{}'s registers in two -% ways. We access registers directly by number rather than tying them -% to control sequence using \cs{int_new:N} and other allocation -% functions. And we store integers in \tn{dimen} registers in scaled -% points (\texttt{sp}), using \TeX{}'s implicit conversion from -% dimensions to integers in some contexts. Specifically, the registers -% are used as follows. When compiling, \tn{toks} registers are used -% under the hood by functions from the \pkg{l3tl-build} module. When -% building, +% We use \pkg{l3intarray} to manipulate arrays of integers (stored into +% some dimension registers in scaled points). We also abuse \TeX{}'s +% \tn{toks} registers, by accessing them directly by number rather than +% tying them to control sequence using the \tn{newtoks} allocation +% functions. Specifically, these arrays and \tn{toks} are used as +% follows. When compiling, \tn{toks} registers are used under the hood +% by functions from the \pkg{l3tl-build} module. When building, +% \tn{toks}\meta{state} holds the tests and actions to perform in the +% \meta{state} of the \textsc{nfa}. When matching, % \begin{itemize} -% \item \tn{toks}\meta{state} holds the tests and actions to perform -% in the \meta{state} of the \textsc{nfa}. -% \item (Not implemented yet.) -% \tn{skip}$i$ has the form \meta{group id} \texttt{plus} -% \meta{left state} \texttt{minus} \meta{right state}. -% \end{itemize} -% When matching, -% \begin{itemize} -% \item \tn{dimen}\meta{state} is equal to the last \meta{step} in -% which the \meta{state} was active. -% \item (Currently, we use \tn{skip} instead of \tn{dimen}.) -% \tn{dimen}\meta{thread}, with $\texttt{min_active} \leq -% \meta{thread} < \texttt{max_active}$, is equal to the -% \meta{state} in which the \meta{thread} currently is. The +% \item \cs{g_@@_state_active_intarray} holds the last \meta{step} in +% which each \meta{state} was active. +% \item \cs{g_@@_thread_state_intarray} maps each \meta{thread} (with +% $\texttt{min_active} \leq \meta{thread} < \texttt{max_active}$) to +% the \meta{state} in which the \meta{thread} currently is. The % \meta{threads} or ordered starting from the best to the least % preferred. % \item \tn{toks}\meta{thread} holds the submatch information for the % \meta{thread}, as the contents of a property list. -% \item \tn{muskip}\meta{position} holds as its main and stretch -% components the character and category code of the token at this +% \item \cs{g_@@_charcode_intarray} and \cs{g_@@_catcode_intarray} hold the +% character codes and category codes of tokens at each % \meta{position} in the query. +% \item \cs{g_@@_balance_intarray} holds the balance of begin-group and +% end-group character tokens which appear before that point in the +% token list. % \item \tn{toks}\meta{position} holds \meta{tokens} which \texttt{o}- % and \texttt{x}-expand to the \meta{position}-th token in the query. -% \item \tn{skip} registers hold the value of end-points of all -% submatches as would be extracted by the \cs{regex_extract} -% functions. Since smaller \tn{skip} registers are used, the minimum -% index is twice \texttt{max_state}, and the used registers go up to -% \cs{l_@@_submatch_int}. They are organized in blocks of -% \texttt{capturing_group}, each block corresponding to one match -% with all its submatches stored in consecutive \tn{skip}s. +% \item \cs{g_@@_submatch_prev_intarray}, \cs{g_@@_submatch_begin_intarray} +% and \cs{g_@@_submatch_end_intarray} hold, for each submatch (as would +% be extracted by \cs{regex_extract_all:nnN}), the place where the +% submatch started to be looked for and its two end-points. For +% historical reasons, the minimum index is twice \texttt{max_state}, +% and the used registers go up to \cs{l_@@_submatch_int}. They are +% organized in blocks of \cs{l_@@_capturing_group_int} entries, each +% block corresponding to one match with all its submatches stored in +% consecutive entries. % \end{itemize} % \tn{count} registers are not abused, which means that we can safely % use named integers in this module. Note that \tn{box} registers are @@ -851,6 +857,89 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[int]{\@@_standard_escapechar:} +% Make the \tn{escapechar} into the standard backslash. +% \begin{macrocode} +\cs_new_protected:Npn \@@_standard_escapechar: + { \int_set:Nn \tex_escapechar:D { `\\ } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int, EXP]{\@@_toks_use:w} +% Unpack a \tn{toks} given its number. +% \begin{macrocode} +\cs_new:Npn \@@_toks_use:w { \tex_the:D \tex_toks:D } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@@_toks_clear:N, \@@_toks_set:Nn, \@@_toks_set:No} +% Empty a \tn{toks} or set it to a value, given its number. +% \begin{macrocode} +\cs_new_protected:Npn \@@_toks_clear:N #1 + { \tex_toks:D #1 { } } +\cs_new_eq:NN \@@_toks_set:Nn \tex_toks:D +\cs_new_protected:Npn \@@_toks_set:No #1 + { \@@_toks_set:Nn #1 \exp_after:wN } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@@_toks_memcpy:NNn} +% Copy |#3| \tn{toks} registers from |#2| onwards to |#1| onwards, +% like |C|'s |memcpy|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_toks_memcpy:NNn #1#2#3 + { + \prg_replicate:nn {#3} + { + \tex_toks:D #1 = \tex_toks:D #2 + \int_incr:N #1 + \int_incr:N #2 + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@@_toks_put_left:Nx} +% \begin{macro}[int]{\@@_toks_put_right:Nx, \@@_toks_put_right:Nn} +% During the building phase we wish to add \texttt{x}-expanded +% material to \tn{toks}, either to the left or to the right. The +% expansion is done \enquote{by hand} for optimization (these +% operations are used quite a lot). The \texttt{Nn} version of +% \cs{@@_toks_put_right:Nx} is provided because it is more +% efficient than \texttt{x}-expanding with \cs{exp_not:n}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_toks_put_left:Nx #1#2 + { + \cs_set:Npx \@@_tmp:w { #2 } + \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN + { \exp_after:wN \@@_tmp:w \tex_the:D \tex_toks:D #1 } + } +\cs_new_protected:Npn \@@_toks_put_right:Nx #1#2 + { + \cs_set:Npx \@@_tmp:w {#2} + \tex_toks:D #1 \exp_after:wN + { \tex_the:D \tex_toks:D \exp_after:wN #1 \@@_tmp:w } + } +\cs_new_protected:Npn \@@_toks_put_right:Nn #1#2 + { \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D #1 #2 } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int, rEXP]{\@@_current_cs_to_str:} +% Expands to the string representation of the token (known to be a +% control sequence) at the current position \cs{l_@@_current_pos_int}. +% It should only be used in \texttt{x}-expansion to avoid losing a +% leading space. +% \begin{macrocode} +\cs_new:Npn \@@_current_cs_to_str: + { + \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N + \tex_the:D \tex_toks:D \l_@@_current_pos_int + } +% \end{macrocode} +% \end{macro} +% % \subsubsection{Constants and variables} % % \begin{macro}[aux]{\@@_tmp:w} @@ -894,14 +983,24 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_balance_int} +% \begin{variable}{\g_@@_charcode_intarray, \g_@@_catcode_intarray, \g_@@_balance_intarray} % The first thing we do when matching is to go once through the query -% token list and store the information for each token as \tn{muskip} -% and \tn{toks} registers. During this phase, \cs{l_@@_balance_int} -% counts the balance of begin-group and end-group character tokens -% which appear before a given point in the token list, and we store it -% as the shrink component of each \tn{muskip} register. This variable -% is also used to keep track of the balance in the replacement text. +% token list and store the information for each token into +% \cs{g_@@_charcode_intarray}, \cs{g_@@_catcode_intarray} and \tn{toks} +% registers. We also store the balance of begin-group/end-group +% characters into \cs{g_@@_balance_intarray}. +% \begin{macrocode} +\__intarray_new:Nn \g_@@_charcode_intarray { 65536 } +\__intarray_new:Nn \g_@@_catcode_intarray { 65536 } +\__intarray_new:Nn \g_@@_balance_intarray { 65536 } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_balance_int} +% During this phase, \cs{l_@@_balance_int} counts the balance of +% begin-group and end-group character tokens which appear before a +% given point in the token list. This variable is also used to keep +% track of the balance in the replacement text. % \begin{macrocode} \int_new:N \l_@@_balance_int % \end{macrocode} @@ -918,6 +1017,20 @@ % % \subsubsection{Testing characters} % +% \begin{macro}{\c_@@_ascii_min_int, \c_@@_ascii_max_control_int, \c_@@_ascii_max_int} +% \begin{macrocode} +\int_const:Nn \c_@@_ascii_min_int { 0 } +\int_const:Nn \c_@@_ascii_max_control_int { 31 } +\int_const:Nn \c_@@_ascii_max_int { 127 } +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\c_@@_ascii_lower_int} +% \begin{macrocode} +\int_const:Nn \c_@@_ascii_lower_int { `a - `A } +% \end{macrocode} +% \end{variable} +% % \begin{macro}[int]{\@@_break_point:TF} % \begin{macro}[int]{\@@_break_true:w} % When testing whether a character of the query token list matches @@ -1027,12 +1140,12 @@ \if_int_compare:w \l_@@_current_char_int > `Z \exp_stop_f: \if_int_compare:w \l_@@_current_char_int > `z \exp_stop_f: \else: \if_int_compare:w \l_@@_current_char_int < `a \exp_stop_f: \else: - \int_sub:Nn \l_@@_case_changed_char_int { \c__str_ascii_lower_int } + \int_sub:Nn \l_@@_case_changed_char_int { \c_@@_ascii_lower_int } \fi: \fi: \else: \if_int_compare:w \l_@@_current_char_int < `A \exp_stop_f: \else: - \int_add:Nn \l_@@_case_changed_char_int { \c__str_ascii_lower_int } + \int_add:Nn \l_@@_case_changed_char_int { \c_@@_ascii_lower_int } \fi: \fi: } @@ -1099,12 +1212,7 @@ \int_compare:nNnTF \l_@@_current_catcode_int = 0 { \tl_set:Nx \l_@@_internal_a_tl - { - \scan_stop: - \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N - \tex_the:D \tex_toks:D \l_@@_current_pos_int - \scan_stop: - } + { \scan_stop: \@@_current_cs_to_str: \scan_stop: } \tl_if_in:noTF { \scan_stop: #1 \scan_stop: } \l_@@_internal_a_tl { \@@_break_true:w } { } } @@ -1128,12 +1236,7 @@ \int_compare:nNnT \l_@@_current_catcode_int = 0 { \group_begin: - \tl_set:Nx \l_@@_cs_name_tl - { - \exp_after:wN \exp_after:wN - \exp_after:wN \cs_to_str:N - \tex_the:D \tex_toks:D \l_@@_current_pos_int - } + \tl_set:Nx \l_@@_cs_name_tl { \@@_current_cs_to_str: } \@@_single_match: \@@_disable_submatches: \@@_build_for_cs:n {#1} @@ -1214,16 +1317,16 @@ \cs_new_protected:Npn \@@_posix_ascii: { \@@_item_caseful_range:nn - \c__str_ascii_min_int - \c__str_ascii_max_int + \c_@@_ascii_min_int + \c_@@_ascii_max_int } \cs_new_eq:NN \@@_posix_blank: \@@_prop_h: \cs_new_protected:Npn \@@_posix_cntrl: { \@@_item_caseful_range:nn - \c__str_ascii_min_int - \c__str_ascii_max_control_int - \@@_item_caseful_equal:n \c__str_ascii_max_int + \c_@@_ascii_min_int + \c_@@_ascii_max_control_int + \@@_item_caseful_equal:n \c_@@_ascii_max_int } \cs_new_eq:NN \@@_posix_digit: \@@_prop_d: \cs_new_protected:Npn \@@_posix_graph: @@ -1301,8 +1404,8 @@ \cs_set:Npn \@@_escape_unescaped:N ##1 { #1 } \cs_set:Npn \@@_escape_escaped:N ##1 { #2 } \cs_set:Npn \@@_escape_raw:N ##1 { #3 } - \int_set:Nn \tex_escapechar:D { `\\ } - \__str_gset_other:Nn \g_@@_internal_tl { #4 } + \@@_standard_escapechar: + \tl_gset:Nx \g_@@_internal_tl { \__str_to_other_fast:n {#4} } \tl_set:Nx \l_@@_internal_b_tl { \exp_after:wN \@@_escape_loop:N \g_@@_internal_tl @@ -1389,12 +1492,11 @@ % % \begin{macro}[aux]{\@@_escape_/x:w} % \begin{macro}[aux]{\@@_escape_x_end:w, \@@_escape_x_large:n} -% When |\x| is encountered, \cs{@@_escape_x_test:N} is responsible -% for grabbing some hexadecimal digits, and feeding the result to -% \cs{@@_escape_x_end:w}. If the number is $<256$, then it is -% turned into a byte and fed to \cs{@@_escape_raw:N}. Otherwise, -% interrupt the assignment, and either produce an error, or use a -% standard \tn{lowercase} trick depending on the precise value. +% When |\x| is encountered, \cs{@@_escape_x_test:N} is responsible for +% grabbing some hexadecimal digits, and feeding the result to +% \cs{@@_escape_x_end:w}. If the number is too big interrupt the +% assignment and produce an error, otherwise call \cs{@@_escape_raw:N} +% on the corresponding character token. % \begin{macrocode} \cs_new:cpn { @@_escape_/x:w } \@@_escape_loop:N { @@ -1403,40 +1505,23 @@ } \cs_new:Npn \@@_escape_x_end:w #1 ; { - \int_compare:nNnTF {#1} > \c__str_max_byte_int - { \@@_escape_x_large:n {#1} } + \int_compare:nNnTF {#1} > \c_max_char_int + { + \if_false: { \fi: } + \__tl_build_one:o \l_@@_internal_b_tl + \__msg_kernel_error:nnx { regex } { x-overflow } {#1} + \tl_set:Nx \l_@@_internal_b_tl + { \if_false: } \fi: + } { \exp_last_unbraced:Nf \@@_escape_raw:N - { \__str_output_byte:n {#1} } + { \char_generate:nn {#1} { 12 } } } } -\group_begin: - \char_set_catcode_other:n { 0 } - \cs_new:Npn \@@_escape_x_large:n #1 - { - \if_false: { \fi: } - \__tl_build_one:o \l_@@_internal_b_tl - \int_compare:nNnTF {#1} > \c_max_char_int - { - \__msg_kernel_error:nnx { regex } { x-overflow } {#1} - \tl_set:Nx \l_@@_internal_b_tl - { \if_false: } \fi: - } - { - \char_set_lccode:nn { 0 } {#1} - \tex_lowercase:D - { - \tl_set:Nx \l_@@_internal_b_tl - { \if_false: } \fi: - \@@_escape_raw:N ^^@ - } - } - } -\group_end: % \end{macrocode} % \end{macro} % \end{macro} -% ^^A todo: use char_generate in above and rest of file +% % \begin{macro}[aux]{\@@_escape_x_test:N, \@@_escape_x_testii:N} % Find out whether the first character is a left brace (allowing any % number of hexadecimal digits), or not (allowing up to two @@ -1461,7 +1546,7 @@ \if_charcode:w \c_left_brace_str #1 \exp_after:wN \@@_escape_x_loop:N \else: - \__str_hexadecimal_use:NTF #1 + \@@_hexadecimal_use:NTF #1 { \exp_after:wN \@@_escape_x:N } { ; \exp_after:wN \@@_escape_loop:N \exp_after:wN #1 } \fi: @@ -1476,7 +1561,7 @@ { \str_if_eq_x:nnTF {#1} { break } { ; } { - \__str_hexadecimal_use:NTF #1 + \@@_hexadecimal_use:NTF #1 { ; \@@_escape_loop:N } { ; \@@_escape_loop:N #1 } } @@ -1494,7 +1579,7 @@ \str_if_eq_x:nnTF {#1} { break } { ; \@@_escape_x_loop_error:n { } {#1} } { - \__str_hexadecimal_use:NTF #1 + \@@_hexadecimal_use:NTF #1 { \@@_escape_x_loop:N } { \token_if_eq_charcode:NNTF \c_space_token #1 @@ -1520,6 +1605,35 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[aux, rEXP]{\@@_hexadecimal_use:NTF} +% \TeX{} detects uppercase hexadecimal digits for us but not the +% lowercase letters, which we need to detect and replace by their +% uppercase counterpart. +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_hexadecimal_use:N #1 { TF } + { + \if_int_compare:w 1 < "1 \token_to_str:N #1 \exp_stop_f: + #1 \prg_return_true: + \else: + \if_case:w \__int_eval:w + \exp_after:wN ` \token_to_str:N #1 - `a + \__int_eval_end: + A + \or: B + \or: C + \or: D + \or: E + \or: F + \else: + \prg_return_false: + \exp_after:wN \use_none:n + \fi: + \prg_return_true: + \fi: + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[EXP, aux] % {\@@_char_if_alphanumeric:NTF, \@@_char_if_special:NTF} % These two tests are used in the first pass when parsing a regular @@ -1549,7 +1663,7 @@ { \if_int_compare:w `#1 > `Z \exp_stop_f: \if_int_compare:w `#1 > `z \exp_stop_f: - \if_int_compare:w `#1 < \c__str_ascii_max_int + \if_int_compare:w `#1 < \c_@@_ascii_max_int \prg_return_true: \else: \prg_return_false: \fi: \else: \if_int_compare:w `#1 < `a \exp_stop_f: @@ -1991,7 +2105,7 @@ \cs_new_protected:Npn \@@_compile:n #1 { \@@_compile:w - \int_set:Nn \tex_escapechar:D { `\\ } + \@@_standard_escapechar: \int_set_eq:NN \l_@@_mode_int \c_@@_outer_mode_int \@@_escape_use:nnnn { @@ -2915,7 +3029,7 @@ { \if_int_odd:w \__int_eval:w \l_@@_catcodes_int / #1 \__int_eval_end: \else: - \tex_advance:D \l_@@_catcodes_int #1 + \int_add:Nn \l_@@_catcodes_int {#1} \fi: } \cs_new_protected:Npn \@@_compile_c_lbrack_end: @@ -3105,8 +3219,8 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_compile_u_in_cs: { - \exp_args:NNo \__str_gset_other:Nn \g_@@_internal_tl - { \l_@@_internal_a_tl } + \tl_gset:Nx \g_@@_internal_tl + { \exp_args:No \__str_to_other_fast:n { \l_@@_internal_a_tl } } \__tl_build_one:x { \tl_map_function:NN \g_@@_internal_tl @@ -3396,10 +3510,11 @@ % \begin{variable}{\l_@@_min_state_int, \l_@@_max_state_int} % The last state that was allocated is $\cs{l_@@_max_state_int}-1$, % so that \cs{l_@@_max_state_int} always points to a free state. -% The \texttt{min_state} variable is always $0$, but is included to -% avoid hard-coding this value. +% The \texttt{min_state} variable is $1$, but is included to +% avoid hard-coding this value everywhere. % \begin{macrocode} \int_new:N \l_@@_min_state_int +\int_set:Nn \l_@@_min_state_int { 1 } \int_new:N \l_@@_max_state_int % \end{macrocode} % \end{variable} @@ -3489,7 +3604,7 @@ \cs_new_protected:Npn \@@_build:N #1 { %<trace> \trace_push:nnn { regex } { 1 } { @@_build } - \int_set:Nn \tex_escapechar:D { `\\ } + \@@_standard_escapechar: \int_zero:N \l_@@_capturing_group_int \int_set_eq:NN \l_@@_max_state_int \l_@@_min_state_int \@@_build_new_state: @@ -3557,33 +3672,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int]{\@@_toks_put_left:Nx} -% \begin{macro}[int]{\@@_toks_put_right:Nx, \@@_toks_put_right:Nn} -% During the building phase we wish to add \texttt{x}-expanded -% material to \tn{toks}, either to the left or to the right. The -% expansion is done \enquote{by hand} for optimization (these -% operations are used quite a lot). The \texttt{Nn} version of -% \cs{@@_toks_put_right:Nx} is provided because it is more -% efficient than \texttt{x}-expanding with \cs{exp_not:n}. -% \begin{macrocode} -\cs_new_protected:Npn \@@_toks_put_left:Nx #1#2 - { - \cs_set:Npx \@@_tmp:w { #2 } - \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN - { \exp_after:wN \@@_tmp:w \tex_the:D \tex_toks:D #1 } - } -\cs_new_protected:Npn \@@_toks_put_right:Nx #1#2 - { - \cs_set:Npx \@@_tmp:w {#2} - \tex_toks:D #1 \exp_after:wN - { \tex_the:D \tex_toks:D \exp_after:wN #1 \@@_tmp:w } - } -\cs_new_protected:Npn \@@_toks_put_right:Nn #1#2 - { \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D #1 #2 } } -% \end{macrocode} -% \end{macro} -% \end{macro} -% % \begin{macro}[int] % { % \@@_build_transition_left:NNN, @@ -3620,7 +3708,7 @@ \int_eval:n { \l_@@_max_state_int + 1 } } %</trace> - \tex_toks:D \l_@@_max_state_int { } + \@@_toks_clear:N \l_@@_max_state_int \int_set_eq:NN \l_@@_left_state_int \l_@@_right_state_int \int_set_eq:NN \l_@@_right_state_int \l_@@_max_state_int \int_incr:N \l_@@_max_state_int @@ -3933,15 +4021,12 @@ ( #1 - 1 ) * ( \l_@@_internal_b_int - \l_@@_internal_a_int ) } - \tex_advance:D \l_@@_right_state_int \l_@@_internal_c_int - \tex_advance:D \l_@@_max_state_int \l_@@_internal_c_int - \prg_replicate:nn \l_@@_internal_c_int - { - \tex_toks:D \l_@@_internal_b_int - = \tex_toks:D \l_@@_internal_a_int - \int_incr:N \l_@@_internal_a_int - \int_incr:N \l_@@_internal_b_int - } + \int_add:Nn \l_@@_right_state_int { \l_@@_internal_c_int } + \int_add:Nn \l_@@_max_state_int { \l_@@_internal_c_int } + \@@_toks_memcpy:NNn + \l_@@_internal_b_int + \l_@@_internal_a_int + \l_@@_internal_c_int \fi: } % \end{macrocode} @@ -4132,7 +4217,7 @@ % transitions, the instruction at the new state of the \textsc{nfa} is % performed immediately. When a transition consumes a character, the % new state is appended to a list of \enquote{active states}, stored in -% \tn{skip} registers: this thread will be active again when the next +% \cs{g_@@_thread_state_intarray}: this thread will be active again when the next % token is read from the query. At every step (for each token in the % query), we unpack that list of active states and the corresponding % submatch props, and empty those. @@ -4176,7 +4261,7 @@ % } % The tokens in the query are indexed from \texttt{min_pos} for the % first to $\texttt{max_pos}-1$ for the last, and their information is -% stored in \tn{muskip} and \tn{toks} registers with those numbers. We +% stored in several arrays and \tn{toks} registers with those numbers. We % don't start from $0$ because the \tn{toks} registers with low % numbers are used to hold the states of the \textsc{nfa}. We match % without backtracking, keeping all threads in lockstep at the @@ -4243,15 +4328,15 @@ % % \begin{variable}{\l_@@_step_int} % This integer, always even, is increased every time a character in -% the query is read, and not reset when doing multiple matches. For -% each \meta{state} in the \textsc{nfa} we store in -% \tn{dimen}\meta{state} the last step in which this state was -% encountered. This lets us break infinite loops by not visiting the -% same state twice in the same step. In fact, \tn{dimen}\meta{state} -% is equal \texttt{step} when we have started performing the -% operations of \tn{toks}\meta{state}, but not finished yet. However, -% once we finish, we set \tn{dimen}\meta{state} to -% $\text{\texttt{step}}+1$. This is needed to track submatches +% the query is read, and not reset when doing multiple matches. We +% store in \cs{g_@@_state_active_intarray} the last step in which each +% \meta{state} in the \textsc{nfa} was encountered. This lets us break +% infinite loops by not visiting the same state twice in the same +% step. In fact, the step we store is equal to \texttt{step} when we +% have started performing the operations of \tn{toks}\meta{state}, but +% not finished yet. However, once we finish, we store +% $\text{\texttt{step}}+1$ in \cs{g_@@_state_active_intarray}. This is +% needed to track submatches % properly (see building phase). The \texttt{step} is also used to % attach each set of submatch information to a given iteration (and % automatically discard it when it corresponds to a past step). @@ -4261,8 +4346,8 @@ % \end{variable} % % \begin{variable}{\l_@@_min_active_int, \l_@@_max_active_int} -% All the currently active states are kept in order of precedence in -% the \tn{skip} registers, and the corresponding submatches in the +% All the currently active threads are kept in order of precedence in +% \cs{g_@@_thread_state_intarray}, and the corresponding submatches in the % \tn{toks}. For our purposes, those serve as an array, indexed from % \texttt{min_active} (inclusive) to \texttt{max_active} (excluded). % At the start of every step, the whole array is unpacked, so that the @@ -4274,6 +4359,17 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\g_@@_state_active_intarray, \g_@@_thread_state_intarray} +% \cs{g_@@_state_active_intarray} stores the last \meta{step} in which +% each \meta{state} was active. \cs{g_@@_thread_state_intarray} stores +% threads that will be considered in the next step, more precisely the +% states in which these threads are. +% \begin{macrocode} +\__intarray_new:Nn \g_@@_state_active_intarray { 65536 } +\__intarray_new:Nn \g_@@_thread_state_intarray { 65536 } +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_every_match_tl} % Every time a match is found, this token list is used. For single % matching, the token list is empty. For multiple matching, the token @@ -4332,11 +4428,11 @@ % \subsubsection{Matching: framework} % % \begin{macro}[int]{\@@_match:n} -% First store the query into \tn{toks} and \tn{muskip} registers (see +% First store the query into \tn{toks} registers and arrays (see % \cs{@@_query_set:nnn}). Then initialize the variables that should % be set once for each user function (even for multiple % matches). Namely, the overall matching is not yet successful; none of -% the states should be marked as visited (\tn{dimen} registers), and +% the states should be marked as visited (\cs{g_@@_state_active_intarray}), and % we start at step $0$; we pretend that there was a previous match % ending at the start of the query, which was not empty (to avoid % smothering an empty match at the start). Once all this is set up, we @@ -4358,12 +4454,13 @@ \bool_gset_false:N \g_@@_success_bool \int_step_inline:nnnn \l_@@_min_state_int { 1 } { \l_@@_max_state_int - 1 } - { \tex_dimen:D ##1 ~ 1 sp \scan_stop: } + { \__intarray_gset_fast:Nnn \g_@@_state_active_intarray {##1} { 1 } } \int_set_eq:NN \l_@@_min_active_int \l_@@_max_state_int \int_zero:N \l_@@_step_int \int_set_eq:NN \l_@@_success_pos_int \l_@@_min_pos_int - \int_set:Nn \l_@@_submatch_int + \int_set:Nn \l_@@_min_submatch_int { 2 * \l_@@_max_state_int } + \int_set_eq:NN \l_@@_submatch_int \l_@@_min_submatch_int \bool_set_false:N \l_@@_empty_success_bool \@@_match_once: %<trace> \trace_pop:nnx { regex } { 1 } { @@_match } @@ -4433,7 +4530,7 @@ % \end{macro} % % \begin{macro}[aux]{\@@_match_loop:} -% \begin{macro}[aux, rEXP]{\@@_match_one_active:w} +% \begin{macro}[aux, rEXP]{\@@_match_one_active:n} % At each new position, set some variables and get the new character % and category from the query. Then unpack the array of active % threads, and clear it by resetting its length @@ -4448,7 +4545,7 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_match_loop: { - \tex_advance:D \l_@@_step_int 2 \exp_stop_f: + \int_add:Nn \l_@@_step_int { 2 } \int_incr:N \l_@@_current_pos_int \int_set_eq:NN \l_@@_last_char_int \l_@@_current_char_int \int_set_eq:NN \l_@@_case_changed_char_int \c_max_int @@ -4456,8 +4553,11 @@ \use:x { \int_set_eq:NN \l_@@_max_active_int \l_@@_min_active_int - \exp_after:wN \@@_match_one_active:w - \int_use:N \l_@@_min_active_int ; + \int_step_function:nnnN + { \l_@@_min_active_int } + { 1 } + { \l_@@_max_active_int - 1 } + \@@_match_one_active:n } \__prg_break_point: \bool_set_false:N \l_@@_fresh_thread_bool %^^A was arg of break_point:n @@ -4467,15 +4567,11 @@ \fi: \fi: } -\cs_new:Npn \@@_match_one_active:w #1; +\cs_new:Npn \@@_match_one_active:n #1 { - \if_int_compare:w #1 < \l_@@_max_active_int - \@@_use_state_and_submatches:nn - { \__int_value:w \tex_skip:D #1 } - { \tex_the:D \tex_toks:D #1 } - \exp_after:wN \@@_match_one_active:w - \__int_value:w \__int_eval:w #1 + 1 \exp_after:wN ; - \fi: + \@@_use_state_and_submatches:nn + { \__intarray_item_fast:Nn \g_@@_thread_state_intarray {#1} } + { \@@_toks_use:w #1 } } % \end{macrocode} % \end{macro} @@ -4485,18 +4581,18 @@ % The arguments are: tokens that \texttt{o} and \texttt{x} expand to % one token of the query, the catcode, and the character code. Store % those, and the current brace balance (used later to check for -% overall brace balance) in a \tn{muskip} register and a \tn{toks}, +% overall brace balance) in a \tn{toks} register and some arrays, % then update the \texttt{balance}. % \begin{macrocode} \cs_new_protected:Npn \@@_query_set:nnn #1#2#3 { - \tex_muskip:D \l_@@_current_pos_int - = \etex_gluetomu:D - #3 sp - plus #2 sp - minus \l_@@_balance_int sp - \scan_stop: - \tex_toks:D \l_@@_current_pos_int {#1} + \__intarray_gset_fast:Nnn \g_@@_charcode_intarray + { \l_@@_current_pos_int } {#3} + \__intarray_gset_fast:Nnn \g_@@_catcode_intarray + { \l_@@_current_pos_int } {#2} + \__intarray_gset_fast:Nnn \g_@@_balance_intarray + { \l_@@_current_pos_int } { \l_@@_balance_int } + \@@_toks_set:Nn \l_@@_current_pos_int {#1} \int_incr:N \l_@@_current_pos_int \if_case:w #2 \exp_stop_f: \or: \int_incr:N \l_@@_balance_int @@ -4507,17 +4603,17 @@ % \end{macro} % % \begin{macro}[aux]{\@@_query_get:} -% Extract the current character and category codes from the -% \tn{muskip} register of the current position: those are the main and -% the stretch components, and we need a conversion to avoid \TeX{}'s -% \enquote{incompatible glue units} error. +% Extract the current character and category codes at the current +% position from the appropriate arrays. % \begin{macrocode} \cs_new_protected:Npn \@@_query_get: { \l_@@_current_char_int - = \etex_mutoglue:D \tex_muskip:D \l_@@_current_pos_int - \l_@@_current_catcode_int = \etex_gluestretch:D - \etex_mutoglue:D \tex_muskip:D \l_@@_current_pos_int + = \__intarray_item_fast:Nn \g_@@_charcode_intarray + { \l_@@_current_pos_int } \scan_stop: + \l_@@_current_catcode_int + = \__intarray_item_fast:Nn \g_@@_catcode_intarray + { \l_@@_current_pos_int } \scan_stop: } % \end{macrocode} % \end{macro} @@ -4537,11 +4633,11 @@ %<*trace> \trace:nnx { regex } { 2 } { state~\int_use:N \l_@@_current_state_int } %</trace> - \tex_dimen:D \l_@@_current_state_int - = \l_@@_step_int sp \scan_stop: - \tex_the:D \tex_toks:D \l_@@_current_state_int - \tex_dimen:D \l_@@_current_state_int - = \__int_eval:w \l_@@_step_int + 1 \__int_eval_end: sp \scan_stop: + \__intarray_gset_fast:Nnn \g_@@_state_active_intarray + { \l_@@_current_state_int } { \l_@@_step_int } + \@@_toks_use:w \l_@@_current_state_int + \__intarray_gset_fast:Nnn \g_@@_state_active_intarray + { \l_@@_current_state_int } { \l_@@_step_int + 1 } } % \end{macrocode} % \end{macro} @@ -4555,7 +4651,9 @@ \cs_new_protected:Npn \@@_use_state_and_submatches:nn #1 #2 { \int_set:Nn \l_@@_current_state_int {#1} - \if_int_compare:w \tex_dimen:D \l_@@_current_state_int + \if_int_compare:w + \__intarray_item_fast:Nn \g_@@_state_active_intarray + { \l_@@_current_state_int } < \l_@@_step_int \tl_set:Nn \l_@@_current_submatches_prop {#2} \exp_after:wN \@@_use_state: @@ -4610,7 +4708,10 @@ \int_add:Nn \l_@@_current_state_int {#2} \exp_not:n { - \if_int_compare:w \tex_dimen:D \l_@@_current_state_int #1 + \if_int_compare:w + \__intarray_item_fast:Nn \g_@@_state_active_intarray + { \l_@@_current_state_int } + #1 \exp_after:wN \@@_use_state: \fi: } @@ -4626,7 +4727,7 @@ % % \begin{macro}[int]{\@@_action_cost:n} % A transition which consumes the current character and shifts the -% state by |#1|. The resulting state is stored in the \tn{skip} array +% state by |#1|. The resulting state is stored in the appropriate array % for use at the next position, and we also store the current % submatches. % \begin{macrocode} @@ -4640,22 +4741,20 @@ % % \begin{macro}[int]{\@@_store_state:n} % \begin{macro}[aux]{\@@_store_submatches:} -% Put the given state in the array of \tn{skip} registers (converted -% to a dimension in scaled points), and increment the length of the -% array. Then store the current submatch in the This is done by -% increasing the pointer \cs{l_@@_max_active_int}, and converting -% the integer to a dimension (suitable for a \tn{skip} assignment) in -% scaled points. +% Put the given state in \cs{g_@@_thread_state_intarray}, and increment +% the length of the array. Also store the current submatch in the +% appropriate \tn{toks}. % \begin{macrocode} \cs_new_protected:Npn \@@_store_state:n #1 { \@@_store_submatches: - \tex_skip:D \l_@@_max_active_int = #1 sp \scan_stop: + \__intarray_gset_fast:Nnn \g_@@_thread_state_intarray + { \l_@@_max_active_int } {#1} \int_incr:N \l_@@_max_active_int } \cs_new_protected:Npn \@@_store_submatches: { - \tex_toks:D \l_@@_max_active_int \exp_after:wN + \@@_toks_set:No \l_@@_max_active_int { \l_@@_current_submatches_prop } } % \end{macrocode} @@ -4729,6 +4828,15 @@ % \end{macrocode} % \end{variable} % +% \begin{variable}{\l_@@_replacement_category_tl, \l_@@_replacement_category_seq} +% This sequence of letters is used to correctly restore categories in +% nested constructions such as |\cL(abc\cD(_)d)|. +% \begin{macrocode} +\tl_new:N \l_@@_replacement_category_tl +\seq_new:N \l_@@_replacement_category_seq +% \end{macrocode} +% \end{variable} +% % \begin{variable}{\l_@@_balance_tl} % This token list holds the replacement text for % \cs{@@_replacement_balance_one_match:n} while it is being built @@ -4739,8 +4847,9 @@ % \end{variable} % % \begin{macro}[aux, rEXP]{\@@_replacement_balance_one_match:n} -% This expects as an argument the first index of a range of \tn{skip} -% registers which hold the submatch information for a given match. It +% This expects as an argument the first index of a set of entries in +% \cs{g_@@_submatch_begin_intarray} (and related arrays) which hold the +% submatch information for a given match. It % can be used within an integer expression to obtain the brace balance % incurred by performing the replacement on that match. This combines % the braces lost by removing the match, braces added by all the @@ -4764,13 +4873,13 @@ % with all possible arguments (one call for each match), as well as % the range from the end of the last match to the end of the string, % will produce the fully replaced token list. The initialization does -% not matter, but we set it as for an empty replacement. +% not matter, but (as an example) we set it as for an empty replacement. % \begin{macrocode} \cs_new:Npn \@@_replacement_do_one_match:n #1 { \@@_query_range:nn - { \etex_glueshrink:D \tex_skip:D #1 } - { \tex_skip:D #1 } + { \__intarray_item_fast:Nn \g_@@_submatch_prev_intarray {#1} } + { \__intarray_item_fast:Nn \g_@@_submatch_begin_intarray {#1} } } % \end{macrocode} % \end{macro} @@ -4816,7 +4925,7 @@ \else: \exp_after:wN \__prg_break: \fi: - \tex_the:D \tex_toks:D #1 \exp_stop_f: + \@@_toks_use:w #1 \exp_stop_f: \exp_after:wN \@@_query_range_loop:ww \__int_value:w \__int_eval:w #1 + 1 ; #2 ; } @@ -4825,17 +4934,13 @@ % \end{macro} % % \begin{macro}[int]{\@@_query_submatch:n} -% When this function is called, \tn{skip}$i$ holds the start and end -% positions for the $i$-th overall submatch as its main and stretch -% components. In the case of repeated matches, submatches from all the -% matches are put one after the other in blocks of -% \cs{l_@@_capturing_group_int} \tn{skip} registers. +% Find the start and end positions for a given submatch (of a given match). % \begin{macrocode} \cs_new:Npn \@@_query_submatch:n #1 { \@@_query_range:nn - { \tex_skip:D \__int_eval:w #1 } - { \etex_gluestretch:D \tex_skip:D \__int_eval:w #1 } + { \__intarray_item_fast:Nn \g_@@_submatch_begin_intarray {#1} } + { \__intarray_item_fast:Nn \g_@@_submatch_end_intarray {#1} } } % \end{macrocode} % \end{macro} @@ -4843,21 +4948,31 @@ % \begin{macro}[rEXP]{\@@_submatch_balance:n} % Every user function must result in a balanced token list (unbalanced % token lists cannot be stored by TeX). When we unpacked the query, we -% kept track of the brace balance as the shrink component of -% \tn{muskip} registers, hence the contribution from a given range is -% the difference between the shrink components of -% \tn{muskip}\meta{max~pos} and \tn{muskip}\meta{min~pos}. For the -% $i$-th submatch, the end-points of the range are the main and -% stretch components of \tn{skip}$i$. The trailing \cs{scan_stop:} is -% gobbled by \cs{etex_muexpr:D}, and the whole expression can be cast -% safely to an integer (no trailing expansion). +% kept track of the brace balance, hence the contribution from a given +% range is the difference between the brace balances at the +% \meta{max~pos} and \meta{min~pos}. These two positions are found in +% the corresponding \enquote{submatch} arrays. +%^^A todo: understand when these int_compare are needed % \begin{macrocode} \cs_new_protected:Npn \@@_submatch_balance:n #1 { - \etex_glueshrink:D \etex_mutoglue:D \etex_muexpr:D - \tex_muskip:D \etex_gluestretch:D \tex_skip:D #1 - - \tex_muskip:D \tex_skip:D #1 - \scan_stop: + \__int_eval:w + \int_compare:nNnTF + { \__intarray_item_fast:Nn \g_@@_submatch_end_intarray {#1} } = 0 + { 0 } + { + \__intarray_item_fast:Nn \g_@@_balance_intarray + { \__intarray_item_fast:Nn \g_@@_submatch_end_intarray {#1} } + } + - + \int_compare:nNnTF + { \__intarray_item_fast:Nn \g_@@_submatch_begin_intarray {#1} } = 0 + { 0 } + { + \__intarray_item_fast:Nn \g_@@_balance_intarray + { \__intarray_item_fast:Nn \g_@@_submatch_begin_intarray {#1} } + } + \__int_eval_end: } % \end{macrocode} % \end{macro} @@ -4886,10 +5001,14 @@ \@@_escape_use:nnnn { \if_charcode:w \c_right_brace_str ##1 - \@@_replacement_rbrace:N \else: \__tl_build_one:n \fi: ##1 + \@@_replacement_rbrace:N + \else: + \@@_replacement_normal:n + \fi: + ##1 } { \@@_replacement_escaped:N ##1 } - { \__tl_build_one:n ##1 } + { \@@_replacement_normal:n ##1 } {#1} \prg_do_nothing: \prg_do_nothing: \if_int_compare:w \l_@@_replacement_csnames_int > 0 \exp_stop_f: @@ -4898,6 +5017,12 @@ \__tl_build_one:x { \prg_replicate:nn \l_@@_replacement_csnames_int \cs_end: } \fi: + \seq_if_empty:NF \l_@@_replacement_category_seq + { + \__msg_kernel_error:nnx { regex } { replacement-missing-rparen } + { \seq_count:N \l_@@_replacement_category_seq } + \seq_clear:N \l_@@_replacement_category_seq + } \cs_gset:Npx \@@_replacement_balance_one_match:n ##1 { + \int_use:N \l_@@_balance_int @@ -4913,8 +5038,8 @@ \cs_set:Npn \@@_replacement_do_one_match:n ##1 { \@@_query_range:nn - { \etex_glueshrink:D \tex_skip:D ##1 } - { \tex_skip:D ##1 } + { \__intarray_item_fast:Nn \g_@@_submatch_prev_intarray {##1} } + { \__intarray_item_fast:Nn \g_@@_submatch_begin_intarray {##1} } #1 } } @@ -4922,6 +5047,35 @@ % \end{macro} % \end{macro} % +% \begin{macro}[aux]{\@@_replacement_normal:n} +% Most characters are simply sent to the output by +% \cs{__tl_build_one:n}, unless a particular category code has been +% requested: then \cs{@@_replacement_c_A:w} or a similar auxiliary is +% called. One exception is right parentheses, which restore the +% category code in place before the group started. Note that the +% sequence is non-empty there: it contains an empty entry +% corresponding to the initial value of +% \cs{l_@@_replacement_category_tl}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_replacement_normal:n #1 + { + \tl_if_empty:NTF \l_@@_replacement_category_tl + { \__tl_build_one:n {#1} } + { % ( + \token_if_eq_charcode:NNTF #1 ) + { + \seq_pop:NN \l_@@_replacement_category_seq + \l_@@_replacement_category_tl + } + { + \use:c { @@_replacement_c_ \l_@@_replacement_category_tl :w } + \@@_replacement_normal:n {#1} + } + } + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[aux]{\@@_replacement_escaped:N} % As in parsing a regular expression, we use an auxiliary built from % |#1| if defined. Otherwise, check for escaped digits (standing from @@ -4935,7 +5089,8 @@ \if_int_compare:w 1 < 1#1 \exp_stop_f: \@@_replacement_put_submatch:n {#1} \else: - \__tl_build_one:o { \token_to_str:N #1 } + \exp_args:No \@@_replacement_normal:n + { \token_to_str:N #1 } \fi: } } @@ -4967,34 +5122,34 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\@@_replacement_g:w, \@@_replacement_g_digits:NN} -% An ugly method to grab digits for the |\g| escape sequence. At the -% end of the run of digits, check that it ends with a right brace. +% \begin{macro}[aux]{\@@_replacement_g:w} +% \begin{macro}[aux,rEXP]{\@@_replacement_g_digits:NN} +% Grab digits for the |\g| escape sequence in a primitive assignment +% to the integer \cs{l_@@_internal_a_int}. At the end of the run of +% digits, check that it ends with a right brace. % \begin{macrocode} \cs_new_protected:Npn \@@_replacement_g:w #1#2 { - \str_if_eq_x:nnTF { #1#2 } { \__tl_build_one:n \c_left_brace_str } - { - \int_zero:N \l_@@_internal_a_int - \@@_replacement_g_digits:NN - } + \str_if_eq_x:nnTF { #1#2 } { \@@_replacement_normal:n \c_left_brace_str } + { \l_@@_internal_a_int = \@@_replacement_g_digits:NN } { \@@_replacement_error:NNN g #1 #2 } } -\cs_new_protected:Npn \@@_replacement_g_digits:NN #1#2 +\cs_new:Npn \@@_replacement_g_digits:NN #1#2 { - \token_if_eq_meaning:NNTF #1 \__tl_build_one:n + \token_if_eq_meaning:NNTF #1 \@@_replacement_normal:n { \if_int_compare:w 1 < 1#2 \exp_stop_f: - \int_set:Nn \l_@@_internal_a_int - { 10 * \l_@@_internal_a_int + #2 } + #2 \exp_after:wN \use_i:nnn \exp_after:wN \@@_replacement_g_digits:NN \else: + \exp_stop_f: \exp_after:wN \@@_replacement_error:NNN \exp_after:wN g \fi: } { + \exp_stop_f: \if_meaning:w \@@_replacement_rbrace:N #1 \exp_args:No \@@_replacement_put_submatch:n { \int_use:N \l_@@_internal_a_int } @@ -5008,41 +5163,52 @@ } % \end{macrocode} % \end{macro} +% \end{macro} % % \subsubsection{Csnames in replacement} % % \begin{macro}[aux]{\@@_replacement_c:w} -% \begin{macro}[aux]+\@@_replacement_c_{:w+ -% |\c| can be followed by a left brace, or by a letter for which we -% have defined a way to produce that category of characters. The -% appropriate definitions for catcodes are introduced later. For -% control sequences, if we are within a control sequence, convert -% the token list to a string, otherwise simply prevent expansion, -% with a weird cross-over between \cs{exp_not:n} and \cs{exp_not:N} -% (see this helper's description for an explanation). +% |\c| may only be followed by an unescaped character. If followed by +% a left brace, start a control sequence by calling an auxiliary +% common with |\u|. Otherwise test whether the category is known; if +% it is not, complain. % \begin{macrocode} \cs_new_protected:Npn \@@_replacement_c:w #1#2 { - \token_if_eq_meaning:NNTF #1 \__tl_build_one:n + \token_if_eq_meaning:NNTF #1 \@@_replacement_normal:n { - \cs_if_exist_use:cF { @@_replacement_c_#2:w } - { \@@_replacement_error:NNN c #1#2 } + \exp_after:wN \token_if_eq_charcode:NNTF \c_left_brace_str #2 + { \@@_replacement_cu_aux:Nw \@@_replacement_exp_not:N } + { + \cs_if_exist:cTF { @@_replacement_c_#2:w } + { \@@_replacement_cat:NNN #2 } + { \@@_replacement_error:NNN c #1#2 } + } } { \@@_replacement_error:NNN c #1#2 } } -\cs_new_protected:cpn { @@_replacement_c_ \c_left_brace_str :w } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux]{\@@_replacement_cu_aux:Nw} +% Start a control sequence with \cs{cs:w}, which will be protected +% from expansion by |#1| (either \cs{@@_replacement_exp_not:N} or +% \cs{exp_not:V}), or turned to a string by \cs{tl_to_str:V} if inside +% another csname construction |\c| or |\u|. We use \cs{tl_to_str:V} +% rather than \cs{tl_to_str:N} to deal with integers and other +% registers. +% \begin{macrocode} +\cs_new_protected:Npn \@@_replacement_cu_aux:Nw #1 { \if_case:w \l_@@_replacement_csnames_int - \__tl_build_one:n - { \exp_not:n { \exp_after:wN \@@_replacement_exp_not:N \cs:w } } + \__tl_build_one:n { \exp_not:n { \exp_after:wN #1 \cs:w } } \else: - \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:N \cs:w } } + \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:V \cs:w } } \fi: \int_incr:N \l_@@_replacement_csnames_int } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}[aux]{\@@_replacement_u:w} % Check that |\u| is followed by a left brace. If so, start a control @@ -5051,15 +5217,8 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_replacement_u:w #1#2 { - \str_if_eq_x:nnTF { #1#2 } { \__tl_build_one:n \c_left_brace_str } - { - \if_case:w \l_@@_replacement_csnames_int - \__tl_build_one:n { \exp_not:n { \exp_after:wN \exp_not:V \cs:w } } - \else: - \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:V \cs:w } } - \fi: - \int_incr:N \l_@@_replacement_csnames_int - } + \str_if_eq_x:nnTF { #1#2 } { \@@_replacement_normal:n \c_left_brace_str } + { \@@_replacement_cu_aux:Nw \exp_not:V } { \@@_replacement_error:NNN u #1#2 } } % \end{macrocode} @@ -5076,7 +5235,7 @@ \__tl_build_one:n \cs_end: \int_decr:N \l_@@_replacement_csnames_int \else: - \__tl_build_one:n #1 + \@@_replacement_normal:n {#1} \fi: } % \end{macrocode} @@ -5084,6 +5243,39 @@ % % \subsubsection{Characters in replacement} % +% \begin{macro}[aux]{\@@_replacement_cat:NNN} +% Here, |#1| is a letter among |BEMTPUDSLOA| and |#2#3| denote the +% next character. Complain if we reach the end of the replacement or +% if the construction appears inside |\c{|\ldots{}|}| or +% |\u{|\ldots{}|}|, and detect the case of a parenthesis. In that +% case, store the current category in a sequence and switch to a new +% one. +% \begin{macrocode} +\cs_new_protected:Npn \@@_replacement_cat:NNN #1#2#3 + { + \token_if_eq_meaning:NNTF \prg_do_nothing: #3 + { \__msg_kernel_error:nn { regex } { replacement-catcode-end } } + { + \int_compare:nNnTF { \l_@@_replacement_csnames_int } > 0 + { + \__msg_kernel_error:nnnn + { regex } { replacement-catcode-in-cs } {#1} {#3} + #2 #3 + } + { + \str_if_eq:nnTF { #2 #3 } { \@@_replacement_normal:n ( } % ) + { + \seq_push:NV \l_@@_replacement_category_seq + \l_@@_replacement_category_tl + \tl_set:Nn \l_@@_replacement_category_tl {#1} + } + { \use:c { @@_replacement_c_#1:w } #2 #3 } + } + } + } +% \end{macrocode} +% \end{macro} +% % We will need to change the category code of the null character many % times, hence work in a group. The catcode-specific macros below are % defined in alphabetical order; if you are trying to understand the @@ -5099,16 +5291,13 @@ % wrapper for our purposes. The first argument is the null character % with various catcodes. The second and third arguments are grabbed % from the input stream: |#3| is the character whose character code to -% reproduce. +% reproduce. We could use \cs{char_generate:nn} but only for some +% catcodes (active characters and spaces are not supported). % \begin{macrocode} \cs_new_protected:Npn \@@_replacement_char:nNN #1#2#3 { - \if_meaning:w \prg_do_nothing: #3 - \__msg_kernel_error:nn { regex } { replacement-catcode-end } - \else: - \tex_lccode:D 0 = `#3 \scan_stop: - \tex_lowercase:D { \__tl_build_one:n {#1} } - \fi: + \tex_lccode:D 0 = `#3 \scan_stop: + \tex_lowercase:D { \__tl_build_one:n {#1} } } % \end{macrocode} % \end{macro} @@ -5234,15 +5423,11 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_replacement_c_S:w #1#2 { - \if_meaning:w \prg_do_nothing: #2 - \__msg_kernel_error:nn { regex } { replacement-catcode-end } - \else: - \if_int_compare:w `#2 = 0 \exp_stop_f: - \__msg_kernel_error:nn { regex } { replacement-null-space } - \fi: - \tex_lccode:D `\ = `#2 \scan_stop: - \tex_lowercase:D { \__tl_build_one:n {~} } + \if_int_compare:w `#2 = 0 \exp_stop_f: + \__msg_kernel_error:nn { regex } { replacement-null-space } \fi: + \tex_lccode:D `\ = `#2 \scan_stop: + \tex_lowercase:D { \__tl_build_one:n {~} } } % \end{macrocode} % \end{macro} @@ -5433,23 +5618,32 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_submatch_int, \l_@@_zeroth_submatch_int} -% The end-points of each submatch are stored as main and stretch -% components of \tn{skip}\meta{submatch}, where \meta{submatch} ranges -% from \cs{l_@@_max_state_int} (inclusive) to +% \begin{variable}{\l_@@_min_submatch_int, \l_@@_submatch_int, \l_@@_zeroth_submatch_int} +% The end-points of each submatch are stored in two arrays whose index \meta{submatch} ranges +% from \cs{l_@@_min_submatch_int} (inclusive) to % \cs{l_@@_submatch_int} (exclusive). Each successful match comes % with a $0$-th submatch (the full match), and one match for each % capturing group: submatches corresponding to the last successful -% match are labelled starting at -% \texttt{zeroth_submatch}. Additionally, the shrink component of this -% $0$-th submatch is the position at which that match attempt started: -% this is used for splitting and replacements. +% match are labelled starting at \texttt{zeroth_submatch}. The entry +% \cs{l_@@_zeroth_submatch_int} in \cs{g_@@_submatch_prev_intarray} holds +% the position at which that match attempt started: this is used for +% splitting and replacements. % \begin{macrocode} +\int_new:N \l_@@_min_submatch_int \int_new:N \l_@@_submatch_int \int_new:N \l_@@_zeroth_submatch_int % \end{macrocode} % \end{variable} % +% \begin{variable}{\g_@@_submatch_prev_intarray, \g_@@_submatch_begin_intarray, \g_@@_submatch_end_intarray} +% Hold the place where the match attempt begun and the end-points of each submatch. +% \begin{macrocode} +\__intarray_new:Nn \g_@@_submatch_prev_intarray { 65536 } +\__intarray_new:Nn \g_@@_submatch_begin_intarray { 65536 } +\__intarray_new:Nn \g_@@_submatch_end_intarray { 65536 } +% \end{macrocode} +% \end{variable} +% % \begin{macro}[aux]{\@@_return:} % This function triggers either \cs{prg_return_false:} or % \cs{prg_return_true:} as appropriate to whether a match was found or @@ -5543,8 +5737,7 @@ % match, store the last part of the token list, which ranges from the % start of the match attempt to the end of the query. This step is % inhibited if the last match was empty and at the very end: decrement -% \cs{l_@@_submatch_int}, which controls which \tn{skip} registers -% will be used. +% \cs{l_@@_submatch_int}, which controls which matches will be used. % \begin{macrocode} \cs_new_protected:Npn \@@_split:nnN #1#2#3 { @@ -5553,16 +5746,30 @@ { \if_int_compare:w \l_@@_start_pos_int < \l_@@_success_pos_int \@@_extract: - \tex_skip:D \l_@@_zeroth_submatch_int - = \l_@@_start_pos_int sp - plus \tex_skip:D \l_@@_zeroth_submatch_int \scan_stop: + \__intarray_gset_fast:Nnn \g_@@_submatch_prev_intarray + { \l_@@_zeroth_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g_@@_submatch_end_intarray + { \l_@@_zeroth_submatch_int } + { + \__intarray_item_fast:Nn \g_@@_submatch_begin_intarray + { \l_@@_zeroth_submatch_int } + } + \__intarray_gset_fast:Nnn \g_@@_submatch_begin_intarray + { \l_@@_zeroth_submatch_int } + { \l_@@_start_pos_int } \fi: } #1 \@@_match:n {#2} %<assert>\assert_int:n { \l_@@_current_pos_int = \l_@@_max_pos_int } - \tex_skip:D \l_@@_submatch_int - = \l_@@_start_pos_int sp plus \l_@@_max_pos_int sp \scan_stop: + \__intarray_gset_fast:Nnn \g_@@_submatch_prev_intarray + { \l_@@_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g_@@_submatch_end_intarray + { \l_@@_submatch_int } + { \l_@@_max_pos_int } + \__intarray_gset_fast:Nnn \g_@@_submatch_begin_intarray + { \l_@@_submatch_int } + { \l_@@_start_pos_int } \int_incr:N \l_@@_submatch_int \if_meaning:w \c_true_bool \l_@@_empty_success_bool \if_int_compare:w \l_@@_start_pos_int = \l_@@_max_pos_int @@ -5575,8 +5782,8 @@ % \end{macro} % % \begin{macro}[aux]{\@@_group_end_extract_seq:N} -% The end-points of submatches are stored as the main and stretch -% components of \tn{skip} registers from \cs{l_@@_max_state_int} to +% The end-points of submatches are stored as entries of two arrays +% from \cs{l_@@_min_submatch_int} to % \cs{l_@@_submatch_int} (exclusive). Extract the relevant ranges % into \cs{l_@@_internal_a_tl}. We detect unbalanced results using % the two flags \texttt{@@_begin} and \texttt{@@_end}, raised @@ -5593,7 +5800,7 @@ { \s__seq \int_step_function:nnnN - { 2 * \l_@@_max_state_int } + { \l_@@_min_submatch_int } { 1 } { \l_@@_submatch_int - 1 } \@@_extract_seq_aux:n @@ -5649,14 +5856,14 @@ % {\@@_extract:, \@@_extract_b:wn, \@@_extract_e:wn} % Our task here is to extract from the property list % \cs{l_@@_success_submatches_prop} the list of end-points of -% submatches, and store them in \tn{skip} registers, from +% submatches, and store them in appropriate array entries, from % \cs{l_@@_zeroth_submatch_int} upwards. We begin by emptying those -% \tn{skip} registers. Then for each \meta{key}--\meta{value} pair in -% the property list update the appropriate \tn{skip} component. This +% entries. Then for each \meta{key}--\meta{value} pair in +% the property list update the appropriate entry. This % is somewhat a hack: the \meta{key} is a non-negative integer % followed by |<| or |>|, which we use in a comparison to $-1$. At the % end, store the information about the position at which the match -% attempt started, as a shrink component. +% attempt started, in \cs{g_@@_submatch_prev_intarray}. % \begin{macrocode} \cs_new_protected:Npn \@@_extract: { @@ -5664,7 +5871,12 @@ \int_set_eq:NN \l_@@_zeroth_submatch_int \l_@@_submatch_int \prg_replicate:nn \l_@@_capturing_group_int { - \tex_skip:D \l_@@_submatch_int 0 sp \scan_stop: + \__intarray_gset_fast:Nnn \g_@@_submatch_begin_intarray + { \l_@@_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g_@@_submatch_end_intarray + { \l_@@_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g_@@_submatch_prev_intarray + { \l_@@_submatch_int } { 0 } \int_incr:N \l_@@_submatch_int } \prop_map_inline:Nn \l_@@_success_submatches_prop @@ -5676,21 +5888,14 @@ \fi: \__int_eval:w \l_@@_zeroth_submatch_int + ##1 {##2} } - \tex_skip:D \l_@@_zeroth_submatch_int - = \tex_the:D \tex_skip:D \l_@@_zeroth_submatch_int - minus \l_@@_start_pos_int sp \scan_stop: + \__intarray_gset_fast:Nnn \g_@@_submatch_prev_intarray + { \l_@@_zeroth_submatch_int } { \l_@@_start_pos_int } \fi: } \cs_new_protected:Npn \@@_extract_b:wn #1 < #2 - { - \tex_skip:D #1 = #2 sp - plus \etex_gluestretch:D \tex_skip:D #1 \scan_stop: - } + { \__intarray_gset_fast:Nnn \g_@@_submatch_begin_intarray {#1} {#2} } \cs_new_protected:Npn \@@_extract_e:wn #1 > #2 - { - \tex_skip:D #1 - = 1 \tex_skip:D #1 plus #2 sp \scan_stop: - } + { \__intarray_gset_fast:Nnn \g_@@_submatch_end_intarray {#1} {#2} } % \end{macrocode} % \end{macro} % @@ -5730,7 +5935,10 @@ { \@@_replacement_do_one_match:n { \l_@@_zeroth_submatch_int } \@@_query_range:nn - { \etex_gluestretch:D \tex_skip:D \l_@@_zeroth_submatch_int } + { + \__intarray_item_fast:Nn \g_@@_submatch_end_intarray + { \l_@@_zeroth_submatch_int } + } { \l_@@_max_pos_int } } \@@_group_end_replace:N #3 @@ -5741,12 +5949,11 @@ % % \begin{macro}[aux]{\@@_replace_all:nnN} % Match multiple times, and for every match, extract submatches and -% additionally store the position at which the match attempt started -% (as the shrink component of a \tn{skip} register). The \tn{skip} -% registers from \cs{l_@@_max_state_int} to +% additionally store the position at which the match attempt started. +% The entries from \cs{l_@@_min_submatch_int} to % \cs{l_@@_submatch_int} hold information about submatches of every % match in order; each match corresponds to -% \cs{l_@@_capturing_group_int} consecutive \tn{skip} registers. +% \cs{l_@@_capturing_group_int} consecutive entries. % Compute the brace balance corresponding to doing all the % replacements: this is the sum of brace balances for replacing each % match. Join together the replacement texts for each match (including @@ -5763,7 +5970,7 @@ { 0 \int_step_function:nnnN - { 2 * \l_@@_max_state_int } + { \l_@@_min_submatch_int } \l_@@_capturing_group_int { \l_@@_submatch_int - 1 } \@@_replacement_balance_one_match:n @@ -5771,7 +5978,7 @@ \tl_set:Nx \l_@@_internal_a_tl { \int_step_function:nnnN - { 2 * \l_@@_max_state_int } + { \l_@@_min_submatch_int } \l_@@_capturing_group_int { \l_@@_submatch_int - 1 } \@@_replacement_do_one_match:n @@ -5825,23 +6032,23 @@ % Messages for the preparsing phase. % \begin{macrocode} \__msg_kernel_new:nnnn { regex } { trailing-backslash } - { Trailing~escape~character~`\iow_char:N\\'. } + { Trailing~escape~character~'\iow_char:N\\'. } { A~regular~expression~or~its~replacement~text~ends~with~ - the~escape~character~`\iow_char:N\\'.~It~will~be~ignored. + the~escape~character~'\iow_char:N\\'.~It~will~be~ignored. } \__msg_kernel_new:nnnn { regex } { x-missing-rbrace } - { Missing~closing~brace~in~`\iow_char:N\\x'~hexadecimal~sequence. } + { Missing~closing~brace~in~'\iow_char:N\\x'~hexadecimal~sequence. } { You~wrote~something~like~ - `\iow_char:N\\x\{...#1'.~ + '\iow_char:N\\x\{...#1'.~ The~closing~brace~is~missing. } \__msg_kernel_new:nnnn { regex } { x-overflow } - { Character~code~`#1'~too~large~in~`\iow_char:N\\x'~hexadecimal~sequence. } + { Character~code~'#1'~too~large~in~'\iow_char:N\\x'~hexadecimal~sequence. } { You~wrote~something~like~ - `\iow_char:N\\x\{\int_to_Hex:n{#1}\}'.~ + '\iow_char:N\\x\{\int_to_Hex:n{#1}\}'.~ The~character~code~#1~is~larger~than~ the~maximum~value~\int_use:N \c_max_char_int. } @@ -5850,11 +6057,11 @@ % Invalid quantifier. % \begin{macrocode} \__msg_kernel_new:nnnn { regex } { invalid-quantifier } - { Braced~quantifier~`#1'~may~not~be~followed~by~`#2'. } + { Braced~quantifier~'#1'~may~not~be~followed~by~'#2'. } { - The~character~`#2'~is~invalid~in~the~braced~quantifier~`#1'.~ - The~only~valid~quantifiers~are~`*',~`?',~`+',~`{<int>}',~ - `{<min>,}'~and~`{<min>,<max>}',~optionally~followed~by~`?'. + The~character~'#2'~is~invalid~in~the~braced~quantifier~'#1'.~ + The~only~valid~quantifiers~are~'*',~'?',~'+',~'{<int>}',~ + '{<min>,}'~and~'{<min>,<max>}',~optionally~followed~by~'?'. } % \end{macrocode} % @@ -5865,7 +6072,7 @@ { Missing~right~bracket~inserted~in~regular~expression. } { LaTeX~was~given~a~regular~expression~where~a~character~class~ - was~started~with~`[',~but~the~matching~`]'~is~missing. + was~started~with~'[',~but~the~matching~']'~is~missing. } \__msg_kernel_new:nnnn { regex } { missing-rparen } { @@ -5889,7 +6096,7 @@ % \begin{macrocode} \__msg_kernel_new:nnnn { regex } { bad-escape } { - Invalid~escape~`\iow_char:N\\#1'~ + Invalid~escape~'\iow_char:N\\#1'~ \@@_if_in_cs:TF { within~a~control~sequence. } { \@@_if_in_class:TF @@ -5898,16 +6105,16 @@ } } { - The~escape~sequence~`\iow_char:N\\#1'~may~not~appear~ + The~escape~sequence~'\iow_char:N\\#1'~may~not~appear~ \@@_if_in_cs:TF { within~a~control~sequence~test~introduced~by~ - `\iow_char:N\\c\iow_char:N\{'. + '\iow_char:N\\c\iow_char:N\{'. } { \@@_if_in_class:TF { within~a~character~class~ } - { following~a~category~test~such~as~`\iow_char:N\\cL'~ } + { following~a~category~test~such~as~'\iow_char:N\\cL'~ } because~it~does~not~match~exactly~one~character. } } @@ -5916,96 +6123,96 @@ % Range errors. % \begin{macrocode} \__msg_kernel_new:nnnn { regex } { range-missing-end } - { Invalid~end-point~for~range~`#1-#2'~in~character~class. } + { Invalid~end-point~for~range~'#1-#2'~in~character~class. } { - The~end-point~`#2'~of~the~range~`#1-#2'~may~not~serve~as~an~ + The~end-point~'#2'~of~the~range~'#1-#2'~may~not~serve~as~an~ end-point~for~a~range:~alphanumeric~characters~should~not~be~ escaped,~and~non-alphanumeric~characters~should~be~escaped. } \__msg_kernel_new:nnnn { regex } { range-backwards } - { Range~`[#1-#2]'~out~of~order~in~character~class. } + { Range~'[#1-#2]'~out~of~order~in~character~class. } { - In~ranges~of~characters~`[x-y]'~appearing~in~character~classes,~ + In~ranges~of~characters~'[x-y]'~appearing~in~character~classes,~ the~first~character~code~must~not~be~larger~than~the~second.~ - Here,~`#1'~has~character~code~\int_eval:n {`#1},~while~ - `#2'~has~character~code~\int_eval:n {`#2}. + Here,~'#1'~has~character~code~\int_eval:n {`#1},~while~ + '#2'~has~character~code~\int_eval:n {`#2}. } % \end{macrocode} % % Errors related to |\c| and |\u|. % \begin{macrocode} \__msg_kernel_new:nnnn { regex } { c-bad-mode } - { Invalid~nested~`\iow_char:N\\c'~escape~in~regular~expression. } + { Invalid~nested~'\iow_char:N\\c'~escape~in~regular~expression. } { - The~`\iow_char:N\\c'~escape~cannot~be~used~within~ - a~control~sequence~test~`\iow_char:N\\c{...}'.~ - To~combine~several~category~tests,~use~`\iow_char:N\\c[...]'. + The~'\iow_char:N\\c'~escape~cannot~be~used~within~ + a~control~sequence~test~'\iow_char:N\\c{...}'.~ + To~combine~several~category~tests,~use~'\iow_char:N\\c[...]'. } \__msg_kernel_new:nnnn { regex } { c-missing-rbrace } - { Missing~right~brace~inserted~for~`\iow_char:N\\c'~escape. } + { Missing~right~brace~inserted~for~'\iow_char:N\\c'~escape. } { LaTeX~was~given~a~regular~expression~where~a~ - `\iow_char:N\\c\iow_char:N\{...'~construction~was~not~ended~ - with~a~closing~brace~`\iow_char:N\}'. + '\iow_char:N\\c\iow_char:N\{...'~construction~was~not~ended~ + with~a~closing~brace~'\iow_char:N\}'. } \__msg_kernel_new:nnnn { regex } { c-missing-rbrack } - { Missing~right~bracket~inserted~for~`\iow_char:N\\c'~escape. } + { Missing~right~bracket~inserted~for~'\iow_char:N\\c'~escape. } { - A~construction~`\iow_char:N\\c[...'~appears~in~a~ - regular~expression,~but~the~closing~`]'~is~not~present. + A~construction~'\iow_char:N\\c[...'~appears~in~a~ + regular~expression,~but~the~closing~']'~is~not~present. } \__msg_kernel_new:nnnn { regex } { c-missing-category } - { Invalid~character~`#1'~following~`\iow_char:N\\c'~escape. } + { Invalid~character~'#1'~following~'\iow_char:N\\c'~escape. } { - In~regular~expressions,~the~`\iow_char:N\\c'~escape~sequence~ + In~regular~expressions,~the~'\iow_char:N\\c'~escape~sequence~ may~only~be~followed~by~a~left~brace,~a~left~bracket,~or~a~ capital~letter~representing~a~character~category,~namely~ - one~of~`ABCDELMOPSTU'. + one~of~'ABCDELMOPSTU'. } \__msg_kernel_new:nnnn { regex } { c-trailing } - { Trailing~category~code~escape~`\iow_char:N\\c'... } + { Trailing~category~code~escape~'\iow_char:N\\c'... } { - A~regular~expression~ends~with~`\iow_char:N\\c'~followed~ + A~regular~expression~ends~with~'\iow_char:N\\c'~followed~ by~a~letter.~It~will~be~ignored. } \__msg_kernel_new:nnnn { regex } { u-missing-lbrace } - { Missing~left~brace~following~`\iow_char:N\\u'~escape. } + { Missing~left~brace~following~'\iow_char:N\\u'~escape. } { - The~`\iow_char:N\\u'~escape~sequence~must~be~followed~by~ + The~'\iow_char:N\\u'~escape~sequence~must~be~followed~by~ a~brace~group~with~the~name~of~the~variable~to~use. } \__msg_kernel_new:nnnn { regex } { u-missing-rbrace } - { Missing~right~brace~inserted~for~`\iow_char:N\\u'~escape. } + { Missing~right~brace~inserted~for~'\iow_char:N\\u'~escape. } { LaTeX~ \str_if_eq_x:nnTF { } {#2} { reached~the~end~of~the~string~ } - { encountered~an~escaped~alphanumeric~character `\iow_char:N\\#2'~ } - when~parsing~the~argument~of~an~`\iow_char:N\\u\iow_char:N\{...\}'~escape. + { encountered~an~escaped~alphanumeric~character '\iow_char:N\\#2'~ } + when~parsing~the~argument~of~an~'\iow_char:N\\u\iow_char:N\{...\}'~escape. } % \end{macrocode} % % Errors when encountering the \textsc{posix} syntax |[:...:]|. % \begin{macrocode} \__msg_kernel_new:nnnn { regex } { posix-unsupported } - { POSIX~collating~element~`[#1 ~ #1]'~not~supported. } + { POSIX~collating~element~'[#1 ~ #1]'~not~supported. } { - The~`[.foo.]'~and~`[=bar=]'~syntaxes~have~a~special~meaning~ + The~'[.foo.]'~and~'[=bar=]'~syntaxes~have~a~special~meaning~ in~POSIX~regular~expressions.~This~is~not~supported~by~LaTeX.~ Maybe~you~forgot~to~escape~a~left~bracket~in~a~character~class? } \__msg_kernel_new:nnnn { regex } { posix-unknown } - { POSIX~class~`[:#1:]'~unknown. } + { POSIX~class~'[:#1:]'~unknown. } { - `[:#1:]'~is~not~among~the~known~POSIX~classes~ - `[:alnum:]',~`[:alpha:]',~`[:ascii:]',~`[:blank:]',~ - `[:cntrl:]',~`[:digit:]',~`[:graph:]',~`[:lower:]',~ - `[:print:]',~`[:punct:]',~`[:space:]',~`[:upper:]',~ - `[:word:]',~and~`[:xdigit:]'. + '[:#1:]'~is~not~among~the~known~POSIX~classes~ + '[:alnum:]',~'[:alpha:]',~'[:ascii:]',~'[:blank:]',~ + '[:cntrl:]',~'[:digit:]',~'[:graph:]',~'[:lower:]',~ + '[:print:]',~'[:punct:]',~'[:space:]',~'[:upper:]',~ + '[:word:]',~and~'[:xdigit:]'. } \__msg_kernel_new:nnnn { regex } { posix-missing-close } - { Missing~closing~`:]'~for~POSIX~class. } - { The~POSIX~syntax~`#1'~must~be~followed~by~`:]',~not~`#2'. } + { Missing~closing~':]'~for~POSIX~class. } + { The~POSIX~syntax~'#1'~must~be~followed~by~':]',~not~'#2'. } % \end{macrocode} % % In various cases, the result of a \pkg{l3regex} operation can leave us @@ -6025,62 +6232,72 @@ % Error message for unknown options. % \begin{macrocode} \__msg_kernel_new:nnnn { regex } { unknown-option } - { Unknown~option~`#1'~for~regular~expressions. } + { Unknown~option~'#1'~for~regular~expressions. } { - The~only~available~option~is~`case-insensitive',~toggled~by~ - `(?i)'~and~`(?-i)'. + The~only~available~option~is~'case-insensitive',~toggled~by~ + '(?i)'~and~'(?-i)'. } \__msg_kernel_new:nnnn { regex } { special-group-unknown } - { Unknown~special~group~`#1~...'~in~a~regular~expression. } + { Unknown~special~group~'#1~...'~in~a~regular~expression. } { - The~only~valid~constructions~starting~with~`(?'~are~ - `(?:~...~)',~`(?|~...~)',~`(?i)',~and~`(?-i)'. + The~only~valid~constructions~starting~with~'(?'~are~ + '(?:~...~)',~'(?|~...~)',~'(?i)',~and~'(?-i)'. } % \end{macrocode} % % Errors in the replacement text. % \begin{macrocode} \__msg_kernel_new:nnnn { regex } { replacement-c } - { Misused~`\iow_char:N\\c'~command~in~a~replacement~text. } + { Misused~'\iow_char:N\\c'~command~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\c'~escape~sequence~ - can~be~followed~by~one~of~the~letters~`ABCDELMOPSTU'~ - or~a~brace~group,~not~by~`#1'. + In~a~replacement~text,~the~'\iow_char:N\\c'~escape~sequence~ + can~be~followed~by~one~of~the~letters~'ABCDELMOPSTU'~ + or~a~brace~group,~not~by~'#1'. } \__msg_kernel_new:nnnn { regex } { replacement-u } - { Misused~`\iow_char:N\\u'~command~in~a~replacement~text. } + { Misused~'\iow_char:N\\u'~command~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\u'~escape~sequence~ + In~a~replacement~text,~the~'\iow_char:N\\u'~escape~sequence~ must~be~~followed~by~a~brace~group~holding~the~name~of~the~ variable~to~use. } \__msg_kernel_new:nnnn { regex } { replacement-g } { - Missing~brace~for~the~`\iow_char:N\\g'~construction~ + Missing~brace~for~the~'\iow_char:N\\g'~construction~ in~a~replacement~text. } { In~the~replacement~text~for~a~regular~expression~search,~ - submatches~are~represented~either~as~`\iow_char:N \\g{dd..d}',~ - or~`\\d',~where~`d'~are~single~digits.~Here,~a~brace~is~missing. + submatches~are~represented~either~as~'\iow_char:N \\g{dd..d}',~ + or~'\\d',~where~'d'~are~single~digits.~Here,~a~brace~is~missing. } \__msg_kernel_new:nnnn { regex } { replacement-catcode-end } { - Missing~character~for~the~`\iow_char:N\\c<category><character>'~ + Missing~character~for~the~'\iow_char:N\\c<category><character>'~ construction~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\c'~escape~sequence~ - can~be~followed~by~one~of~the~letters~`ABCDELMOPSTU'~representing~ + In~a~replacement~text,~the~'\iow_char:N\\c'~escape~sequence~ + can~be~followed~by~one~of~the~letters~'ABCDELMOPSTU'~representing~ the~character~category.~Then,~a~character~must~follow.~LaTeX~ reached~the~end~of~the~replacement~when~looking~for~that. } +\__msg_kernel_new:nnnn { regex } { replacement-catcode-in-cs } + { + Category~code~'\iow_char:N\\c#1#3'~ignored~inside~ + '\iow_char:N\\c\{...\}'~in~a~replacement~text. + } + { + In~a~replacement~text,~the~category~codes~of~the~argument~of~ + '\iow_char:N\\c\{...\}'~are~ignored~when~building~the~control~ + sequence~name. + } \__msg_kernel_new:nnnn { regex } { replacement-null-space } { TeX~cannot~build~a~space~token~with~character~code~0. } { You~asked~for~a~character~token~with~category~space,~ and~character~code~0,~for~instance~through~ - `\iow_char:N\\cS\iow_char:N\\x00'.~ + '\iow_char:N\\cS\iow_char:N\\x00'.~ This~specific~case~is~impossible~and~will~be~replaced~ by~a~normal~space. } @@ -6090,6 +6307,12 @@ There~ \int_compare:nTF { #1 = 1 } { was } { were } ~ #1~ missing~right~\int_compare:nTF { #1 = 1 } { brace } { braces } . } +\__msg_kernel_new:nnnn { regex } { replacement-missing-rparen } + { Missing~right~parenthesis~inserted~in~replacement~text. } + { + There~ \int_compare:nTF { #1 = 1 } { was } { were } ~ #1~ + missing~right~\int_compare:nTF { #1 = 1 } { parenthesis } { parentheses } . + } % \end{macrocode} % % \begin{macro}[aux]{\@@_msg_repeated:nnN} @@ -6136,7 +6359,7 @@ { \l_@@_max_state_int - 1 } { \trace:nnx { regex } { #1 } - { \iow_char:N \\toks ##1 = { \tex_the:D \tex_toks:D ##1 } } + { \iow_char:N \\toks ##1 = { \@@_toks_use:w ##1 } } } } %</trace> diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx index 0f5e21f0514..4e4b8c3959b 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-convert.dtx @@ -47,7 +47,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -192,15 +192,6 @@ % % \section{Internal string functions} % -% \begin{function}{\__str_gset_other:Nn} -% \begin{syntax} -% \cs{__str_gset_other:Nn} \meta{tl~var} \Arg{token list} -% \end{syntax} -% Converts the \meta{token list} to an \meta{other string}, where -% spaces have category code \enquote{other}, and assigns the result to -% the \meta{tl~var}, globally. -% \end{function} -% % \begin{function}{\__str_hexadecimal_use:NTF} % \begin{syntax} % \cs{__str_hexadecimal_use:NTF} \meta{token} \Arg{true code} \Arg{false code} @@ -216,17 +207,6 @@ % \end{texnote} % \end{function} % -% \begin{function}[EXP]{\__str_output_byte:n} -% \begin{syntax} -% \cs{__str_output_byte:n} \Arg{intexpr} -% \end{syntax} -% Expands to a character token with category other and character code -% equal to the value of \meta{intexpr}. The value of \meta{intexpr} -% must be in the range $[-1, 255]$, and any value outside this range -% results in undefined behaviour. The special value $-1$ is used to -% produce an empty result. -% \end{function} -% % \section{Possibilities, and things to do} % % Encoding/escaping-related tasks. @@ -272,7 +252,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{l3str-convert}{2017/04/01}{} +\ProvidesExplPackage{l3str-convert}{2017/05/13}{} {L3 Experimental string encoding conversions} \RequirePackage{l3tl-analysis,l3tl-build} % \end{macrocode} @@ -330,20 +310,6 @@ % \end{macrocode} % \end{variable} % -% \begin{macro}{\c_@@_ascii_min_int, \c_@@_ascii_max_control_int, \c_@@_ascii_max_int} -% \begin{macrocode} -\int_const:Nn \c_@@_ascii_min_int { 0 } -\int_const:Nn \c_@@_ascii_max_control_int { 31 } -\int_const:Nn \c_@@_ascii_max_int { 127 } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[aux]{\c_@@_ascii_lower_int} -% \begin{macrocode} -\int_const:Nn \c_@@_ascii_lower_int { `a - `A } -% \end{macrocode} -% \end{macro} -% % \begin{variable}{\g_@@_alias_prop} % To avoid needing one file per encoding/escaping alias, we keep track % of those in a property list. @@ -387,48 +353,6 @@ % \end{macrocode} % \end{variable} % -% \subsubsection{Escaping spaces} -% ^^A todo: use char_generate in this file -% \begin{macro}[int]{\@@_gset_other:Nn} -% \begin{macro}[aux,EXP]{\@@_gset_other_loop:w} -% \begin{macro}[aux,EXP]{\@@_gset_other_end:w} -% This function could be done by using \cs{@@_to_other:n} within -% an \texttt{x}-expansion, but that would take a time quadratic in the -% size of the string. Instead, we can \enquote{leave the result behind -% us} in the input stream, to be captured into the expanding -% assignment. This gives us a linear time. -% \begin{macrocode} -\group_begin: -\char_set_lccode:nn { `\* } { `\ } -\char_set_lccode:nn { `\A } { `\A } -\tex_lowercase:D - { - \group_end: - \cs_new_protected:Npn \@@_gset_other:Nn #1#2 - { - \tl_gset:Nx #1 - { - \exp_after:wN \@@_gset_other_loop:w \tl_to_str:n {#2} ~ % - A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_stop - } - } - \cs_new:Npn \@@_gset_other_loop:w - #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 ~ - { - \if_meaning:w A #9 - \@@_gset_other_end:w - \fi: - #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * #9 - \@@_gset_other_loop:w * - } - \cs_new:Npn \@@_gset_other_end:w \fi: #1 * A #2 \q_stop - { \fi: #1 } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% % \subsection{String conditionals} % % \begin{macro}[EXP]{\@@_if_contains_char:NNT, \@@_if_contains_char:NNTF} @@ -544,12 +468,12 @@ % an empty result for the input $-1$. % \begin{macrocode} \group_begin: - \tl_set:Nx \l__str_internal_tl { \tl_to_str:n { 0123456789ABCDEF } } - \tl_map_inline:Nn \l__str_internal_tl + \tl_set:Nx \l_@@_internal_tl { \tl_to_str:n { 0123456789ABCDEF } } + \tl_map_inline:Nn \l_@@_internal_tl { - \tl_map_inline:Nn \l__str_internal_tl + \tl_map_inline:Nn \l_@@_internal_tl { - \tl_const:cx { c__str_byte_ \int_eval:n {"#1##1} _tl } + \tl_const:cx { c_@@_byte_ \int_eval:n {"#1##1} _tl } { \char_generate:nn { "#1##1 } { 12 } #1 ##1 } } } @@ -783,7 +707,7 @@ { \group_begin: #1 - \@@_gset_other:Nn \g_@@_result_tl {#4} + \tl_gset:Nx \g_@@_result_tl { \@@_to_other_fast:n {#4} } \exp_after:wN \@@_convert:wwwnn \tl_to_str:n {#5} /// \q_stop { decode } { unescape } @@ -951,7 +875,7 @@ #1 \fi: \else: - \@@_output_byte:n { `#1 + \c_@@_ascii_lower_int } + \@@_output_byte:n { `#1 + `a - `A } \fi: \fi: \@@_convert_lowercase_alphanum_loop:N diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx index 6619f9c9b06..c61d2575e90 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx @@ -47,7 +47,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -163,7 +163,7 @@ % % \begin{macrocode} %<*package> -\ProvidesExplPackage{l3str-format}{2017/04/01}{} +\ProvidesExplPackage{l3str-format}{2017/05/13}{} {L3 Experimental string formatting} \RequirePackage{l3str} %</package> diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.ins b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.ins index 56c80ce4992..be46fd21845 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.ins +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.ins @@ -1,6 +1,6 @@ \iffalse meta-comment -File l3str.ins Copyright (C) 2011,2013,2015,2016 The LaTeX3 Project +File l3str.ins Copyright (C) 2011,2013,2015-2017 The LaTeX3 Project It may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this @@ -32,7 +32,7 @@ license information is placed in the derived files. \preamble -Copyright (C) 2011-2016 The LaTeX3 Project +Copyright (C) 2011-2017 The LaTeX3 Project It may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of @@ -57,6 +57,7 @@ and all files in that bundle must be distributed together. \generate{\file{l3tl-analysis.sty} {\from{l3tl-analysis.dtx} {package}}} \generate{\file{l3tl-build.sty} {\from{l3tl-build.dtx} {package}}} \generate{\file{l3regex-trace.sty} {\from{l3regex.dtx} {package,trace}}} +\generate{\file{l3intarray.sty} {\from{l3intarray.dtx} {package}}} % Escapings. \generate{% diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-analysis.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-analysis.dtx index 44b024c95c0..5dd95a5e208 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-analysis.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-analysis.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -171,7 +171,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{l3tl-analysis}{2017/04/01}{} +\ProvidesExplPackage{l3tl-analysis}{2017/05/13}{} {L3 Experimental token list analysis} % \end{macrocode} % @@ -390,15 +390,17 @@ % must appear in its string representation. The string is shortened % a little by making the escape character unprintable. The active % space must be disabled separately (the loop skips over it otherwise), -% and we end the loop by feeding an odd non-\texttt{N}-type -% argument to the looping macro. +% and we end the loop by feeding an odd non-\texttt{N}-type argument +% to the looping macro. For \pTeX{} and \upTeX{} we skip characters +% beyond $[0,255]$ because \tn{lccode} only allows those values. % \begin{macrocode} \cs_new_protected:Npn \@@_setup:n #1 { \int_set:Nn \tex_escapechar:D { -1 } \exp_after:wN \@@_disable_loop:N - \tl_to_str:n {#1} { ~ } { ? ~ \__prg_break: } + \tl_to_str:n {#1} { ~ } { ? \__prg_break: } \__prg_break_point: + \scan_stop: } \group_begin: \char_set_catcode_active:N \^^@ @@ -408,6 +410,20 @@ \tex_lowercase:D { \tex_let:D ^^@ } \tex_undefined:D \@@_disable_loop:N } + \bool_lazy_or:nnT + { \sys_if_engine_ptex_p: } + { \sys_if_engine_uptex_p: } + { + \cs_gset_protected:Npn \@@_disable_loop:N #1 + { + \use_none:n #1 \scan_stop: + \if_int_compare:w 256 > `#1 \exp_stop_f: + \tex_lccode:D 0 = `#1 ~ + \tex_lowercase:D { \tex_let:D ^^@ } \tex_undefined:D + \fi: + \@@_disable_loop:N + } + } \group_end: % \end{macrocode} % \end{macro} diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx index 70823439c5c..bbdb3958613 100644 --- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3tl-build.dtx @@ -23,8 +23,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/04/01] -%<package>\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} %<package> {} %<package> {% %<package> \PackageError{l3tl-build}{Support package l3kernel too old} @@ -60,7 +60,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -150,7 +150,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{l3tl-build}{2017/04/01}{} +\ProvidesExplPackage{l3tl-build}{2017/05/13}{} {L3 Experimental token list construction} % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx b/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx index 0969c705e68..59439b2b93f 100644 --- a/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx @@ -54,7 +54,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -113,10 +113,6 @@ % Before any alignment can take place, coffins must be created and % their contents must be created. All coffin operations are local % to the current \TeX{} group with the exception of coffin creation. -% Coffins are also \enquote{color safe}: in contrast to the code-level -% \cs{box_\ldots} functions there is no need to add additional grouping -% to coffins when dealing with color. -% % \begin{function}{\NewCoffin} % \begin{syntax} % \cs{NewCoffin} \meta{coffin} @@ -677,7 +673,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xcoffins}{2017/04/01}{} +\ProvidesExplPackage{xcoffins}{2017/05/13}{} {L3 Experimental design level coffins} % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx b/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx index adda76b48f4..b29e9fa8364 100644 --- a/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx @@ -24,8 +24,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/04/01] -%<package>\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} %<package> {} %<package> {% %<package> \PackageError{l3galley}{Support package l3kernel too old} @@ -59,7 +59,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -146,9 +146,8 @@ % \cs{galley_level:} % \end{syntax} % Sets up a vertical box to contain a new galley level. The box should -% be \enquote{color safe}, which is automatic for \LaTeX3 coffins but -% must be included manually (using \cs{color_group_begin:} and -% \cs{color_group_end:}) in \enquote{raw} vertical boxes. +% include \enquote{wrapper} group (be \enquote{color safe}): this is +% automatically true for all \LaTeX3 boxes and coffins. % \end{function} % % \subsection{Measure} @@ -686,7 +685,7 @@ % % \begin{macrocode} %<*package> -\ProvidesExplPackage{l3galley}{2017/04/01}{} +\ProvidesExplPackage{l3galley}{2017/05/13}{} {L3 Experimental galley code} %</package> % \end{macrocode} @@ -1285,7 +1284,7 @@ \cs_new_protected:Npn \galley_par:n #1 { \s__par_omit - \bool_if:nF \g_@@_begin_level_bool + \bool_if:NF \g_@@_begin_level_bool { #1 \galley_par: diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx index dcf162d0283..00b6928e4bc 100644 --- a/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx +++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx @@ -45,7 +45,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -732,7 +732,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xgalley}{2017/04/01}{} +\ProvidesExplPackage{xgalley}{2017/05/13}{} {L3 Experimental galley} \RequirePackage{xparse,xtemplate,l3galley} % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx index c9de1d0f8b7..eaee0f7a59d 100644 --- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx @@ -21,7 +21,7 @@ % for those people who are interested. % %<*driver|generic|package> -\def\ExplFileDate{2017/04/01}% +\def\ExplFileDate{2017/05/13}% %</driver|generic|package> %<*driver> \documentclass[full]{l3doc} @@ -49,7 +49,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -1292,11 +1292,9 @@ \sys_if_output_pdf:TF { pdfmode } { - \bool_if:nTF - { - \sys_if_engine_pdftex_p: || - \sys_if_engine_luatex_p: - } + \bool_lazy_or:nnTF + { \sys_if_engine_pdftex_p: } + { \sys_if_engine_luatex_p: } { dvips } { dvipdfmx } } @@ -1417,7 +1415,7 @@ % \begin{macro} % { % \box_rotate:Nn, -% \box_resize:Nnn, +% \box_resize_to_wd_and_ht_plus_dp:Nnn, % \box_resize_to_ht_plus_dp:Nn, % \box_resize_to_wd:Nn, % \box_scale:Nnn @@ -1444,7 +1442,7 @@ } \cs_set_protected:Npn \box_rotate:Nn #1#2 { \hbox_set:Nn #1 { \rotatebox {#2} { \box_use:N #1 } } } - \cs_set_protected:Npn \box_resize:Nnn #1#2#3 + \cs_set_protected:Npn \box_resize_to_wd_and_ht_plus_dp:Nnn #1#2#3 { \hbox_set:Nn #1 { @@ -1470,15 +1468,13 @@ { \box_use:N #1 } } } - \cs_set_protected:Npn \box_scale:Nnn #1#2#3 + \cs_set_protected:Npn \__box_scale_aux:N #1 { - \hbox_set:Nn #1 - { - \exp_last_unbraced:Nx \scalebox - { { \fp_eval:n {#2} } [ \fp_eval:n {#3} ] } - { \box_use:N #1 } - } + \exp_last_unbraced:Nx \scalebox + { { \fp_use:N \l__box_scale_x_fp } [ \fp_use:N \l__box_scale_y_fp ] } + { \box_use:N #1 } } + \cs_set_protected:Npn \color_ensure_current: { \set@color } } % \end{macrocode} % \end{macro} @@ -1678,11 +1674,6 @@ % \end{macrocode} % \end{macro} % -% Deactivate writing module information to the log. -% \begin{macrocode} -\protected\def\GetIdInfoLog{} -% \end{macrocode} -% % For driver loading in generic mode, there are no options: pick the most % appropriate case! To allow this loading to take place a temporary % definition of \cs{ProvidesExplFile} is provided diff --git a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx index 078f3016465..1e94b66f730 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx index 3310d9336f2..7b895ee75d0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx index 5001f7340af..db8e9826e3b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx @@ -21,7 +21,7 @@ % for those people who are interested. % %<*driver|package> -% \begin{macro}[deprecated = 2017-03-19]{\GetIdInfo} +% \begin{macro}{\GetIdInfo} % \begin{macro}[aux]{\GetIdInfoAuxI, \GetIdInfoAuxII, \GetIdInfoAuxIII} % The idea here is to extract out the information needed from a standard % \textsc{svn} \texttt{Id} line, but without a line that will get @@ -139,7 +139,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -187,11 +187,30 @@ % the package identifier line. % \end{function} % +% \begin{function}[updated = 2012-06-04]{\GetIdInfo} +% \begin{syntax} +% |\RequirePackage{l3bootstrap}| +% \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. +% 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} % % \subsection{Internal functions and variables} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx index edbf6b7b652..b7ac16ab656 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -335,9 +335,14 @@ % group levels. % \end{function} % +% \section{Boxes and color} +% +% All \LaTeX{}3 boxes are \enquote{color safe}: a color set inside the box +% will not apply after the end of the box has occurred. +% % \section{Horizontal mode boxes} % -% \begin{function}{\hbox:n} +% \begin{function}[updated = 2017-04-05]{\hbox:n} % \begin{syntax} % \cs{hbox:n} \Arg{contents} % \end{syntax} @@ -345,7 +350,7 @@ % width and then includes this box in the current list for typesetting. % \end{function} % -% \begin{function}{\hbox_to_wd:nn} +% \begin{function}[updated = 2017-04-05]{\hbox_to_wd:nn} % \begin{syntax} % \cs{hbox_to_wd:nn} \Arg{dimexpr} \Arg{contents} % \end{syntax} @@ -354,7 +359,7 @@ % typesetting. % \end{function} % -% \begin{function}{\hbox_to_zero:n} +% \begin{function}[updated = 2017-04-05]{\hbox_to_zero:n} % \begin{syntax} % \cs{hbox_to_zero:n} \Arg{contents} % \end{syntax} @@ -362,7 +367,8 @@ % and then includes this box in the current list for typesetting. % \end{function} % -% \begin{function}{\hbox_set:Nn, \hbox_set:cn, \hbox_gset:Nn, \hbox_gset:cn} +% \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} @@ -370,7 +376,7 @@ % result inside the \meta{box}. % \end{function} % -% \begin{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 @@ -382,7 +388,7 @@ % and then stores the result inside the \meta{box}. % \end{function} % -% \begin{function}{\hbox_overlap_right:n} +% \begin{function}[updated = 2017-04-05]{\hbox_overlap_right:n} % \begin{syntax} % \cs{hbox_overlap_right:n} \Arg{contents} % \end{syntax} @@ -391,7 +397,7 @@ % point. % \end{function} % -% \begin{function}{\hbox_overlap_left:n} +% \begin{function}[updated = 2017-04-05]{\hbox_overlap_left:n} % \begin{syntax} % \cs{hbox_overlap_left:n} \Arg{contents} % \end{syntax} @@ -400,7 +406,7 @@ % point. % \end{function} % -% \begin{function} +% \begin{function}[updated = 2017-04-05] % { % \hbox_set:Nw, \hbox_set:cw, % \hbox_set_end:, @@ -451,18 +457,15 @@ % is that of the first item added. These tend to have a large depth and % small height, although the latter will typically be non-zero. % -% \begin{function}[updated = 2011-12-18]{\vbox:n} +% \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. -% \begin{texnote} -% This is the \TeX{} primitive \tn{vbox}. -% \end{texnote} % \end{function} % -% \begin{function}[updated = 2011-12-18]{\vbox_top:n} +% \begin{function}[updated = 2017-04-05]{\vbox_top:n} % \begin{syntax} % \cs{vbox_top:n} \Arg{contents} % \end{syntax} @@ -470,12 +473,9 @@ % and includes this box in the current list for typesetting. The % baseline of the box will be equal to that of the \emph{first} % item added to the box. -% \begin{texnote} -% This is the \TeX{} primitive \tn{vtop}. -% \end{texnote} % \end{function} % -% \begin{function}[updated = 2011-12-18]{\vbox_to_ht:nn} +% \begin{function}[updated = 2017-04-05]{\vbox_to_ht:nn} % \begin{syntax} % \cs{vbox_to_ht:nn} \Arg{dimexpr} \Arg{contents} % \end{syntax} @@ -484,7 +484,7 @@ % typesetting. % \end{function} % -% \begin{function}[updated = 2011-12-18]{\vbox_to_zero:n} +% \begin{function}[updated = 2017-04-05]{\vbox_to_zero:n} % \begin{syntax} % \cs{vbox_to_zero:n} \Arg{contents} % \end{syntax} @@ -492,7 +492,7 @@ % and then includes this box in the current list for typesetting. % \end{function} % -% \begin{function}[updated = 2011-12-18] +% \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} @@ -501,7 +501,7 @@ % result inside the \meta{box}. % \end{function} % -% \begin{function}[updated = 2011-12-18] +% \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} @@ -511,7 +511,7 @@ % to that of the \emph{first} item added to the box. % \end{function} % -% \begin{function}[updated = 2011-12-18] +% \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 @@ -523,7 +523,7 @@ % \meta{dimexpr} and then stores the result inside the \meta{box}. % \end{function} % -% \begin{function}[updated = 2011-12-18] +% \begin{function}[updated = 2017-04-058] % { % \vbox_set:Nw, \vbox_set:cw, % \vbox_set_end:, @@ -575,6 +575,162 @@ % \end{texnote} % \end{function} % +% \subsection{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] +% {\box_autosize_to_wd_and_ht:Nnn, \box_autosize_to_wd_and_ht:Nnn} +% \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} will be an |hbox|, irrespective of the nature +% of the \meta{box} before the resizing is applied. The final size of the +% \meta{box} will be the smaller of \Arg{x-size} and \Arg{y-size}, +% \emph{i.e.}~the result will fit within the dimensions specified. Negative +% sizes will cause the material in the \meta{box} to be reversed in direction, +% but the reference point of the \meta{box} will be unchanged. Thus a negative +% \meta{y-size} will result in the \meta{box} having a depth dependent on the +% height of the original and \emph{vice versa}. The resizing applies within +% the current \TeX{} group level. +% \end{function} +% +% \begin{function}[added = 2017-04-04] +% {\box_autosize_to_wd_and_ht_plus_dp:Nnn, \box_autosize_to_wd_and_ht_plus_dp:Nnn} +% \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} will be an |hbox|, irrespective of the nature +% of the \meta{box} before the resizing is applied. The final size of the +% \meta{box} will be the smaller of \Arg{x-size} and \Arg{y-size}, +% \emph{i.e.}~the result will fit within the dimensions specified. Negative +% sizes will cause the material in the \meta{box} to be reversed in direction, +% but the reference point of the \meta{box} will be unchanged. Thus a negative +% \meta{y-size} will result in the \meta{box} having a depth dependent on the +% height of the original and \emph{vice versa}. The resizing applies within +% the current \TeX{} group level. +% \end{function} +% +% \begin{function} +% {\box_resize_to_ht:Nn, \box_resize_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} will be an |hbox|, irrespective of the nature of the \meta{box} +% before the resizing is applied. A negative \meta{y-size} will cause the +% material in the \meta{box} to be reversed in direction, but the reference +% point of the \meta{box} will be unchanged. Thus a negative \meta{y-size} +% will result in the \meta{box} having a depth dependent on the height of the +% original and \emph{vice versa}. The resizing applies within the current +% \TeX{} group level. +% \end{function} +% +% \begin{function} +% {\box_resize_to_ht_plus_dp:Nn, \box_resize_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} will be an |hbox|, irrespective of the nature of the \meta{box} +% before the resizing is applied. A negative \meta{y-size} will cause +% the material in the \meta{box} to be reversed in direction, but the +% reference point of the \meta{box} will be unchanged. Thus a negative +% \meta{y-size} will result in the \meta{box} having a depth dependent on the +% height of the original and \emph{vice versa}. The resizing applies within +% the current \TeX{} group level. +% \end{function} +% +% \begin{function}{\box_resize_to_wd:Nn, \box_resize_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} will be an |hbox|, irrespective of the nature of the \meta{box} +% before the resizing is applied. A negative \meta{x-size} will cause the +% material in the \meta{box} to be reversed in direction, but the reference +% point of the \meta{box} will be unchanged. Thus a negative \meta{x-size} +% will result in the \meta{box} having a depth dependent on the height of the +% original and \emph{vice versa}. The resizing applies within the current +% \TeX{} group level. +% \end{function} +% +% \begin{function}[added = 2014-07-03] +% {\box_resize_to_wd_and_ht:Nnn, \box_resize_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} will be an |hbox|, irrespective of the nature of the \meta{box} +% before the resizing is applied. Negative sizes will cause the material in +% the \meta{box} to be reversed in direction, but the reference point of the +% \meta{box} will be unchanged. Thus a negative \meta{y-size} will result in +% the \meta{box} having a depth dependent on the height of the original and +% \emph{vice versa}. The resizing applies within the current \TeX{} group +% level. +% \end{function} +% +% \begin{function}[added = 2017-04-06] +% {\box_resize_to_wd_and_ht_plus_dp:Nnn, \box_resize_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} will be an |hbox|, irrespective of the nature of the \meta{box} +% before the resizing is applied. Negative sizes will cause the material in +% the \meta{box} to be reversed in direction, but the reference point of the +% \meta{box} will be unchanged. Thus a negative \meta{y-size} will result in +% the \meta{box} having a depth dependent on the height of the original and +% \emph{vice versa}. The resizing applies within the current \TeX{} group +% level. +% \end{function} +% +% \begin{function}{\box_rotate:Nn, \box_rotate:cn} +% \begin{syntax} +% \cs{box_rotate:Nn} \meta{box} \Arg{angle} +% \end{syntax} +% Rotates the \meta{box} by \meta{angle} (in degrees) anti-clockwise about +% its reference point. The reference point of the updated box will be moved +% horizontally such that it is at the left side of the smallest rectangle +% enclosing the rotated material. The updated \meta{box} will be an |hbox|, +% irrespective of the nature of the \meta{box} before the rotation is applied. +% The rotation applies within the current \TeX{} group level. +% \end{function} +% +% \begin{function}{\box_scale:Nnn, \box_scale: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 +% integer expressions). The updated \meta{box} will be an |hbox|, irrespective +% of the nature of the \meta{box} before the scaling is applied. Negative +% scalings will cause the material in the \meta{box} to be reversed in +% direction, but the reference point of the \meta{box} will be unchanged. +% Thus a negative \meta{y-scale} will result in the \meta{box} having a depth +% dependent on the height of the original and \emph{vice versa}. The resizing +% applies within the current \TeX{} group level. +% \end{function} +% % \section{Primitive box conditionals} % % \begin{function}[EXP]{\if_hbox:N} @@ -976,7 +1132,8 @@ % \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: {#1} } +\cs_new_protected:Npn \hbox:n #1 + { \tex_hbox:D \scan_stop: { \group_begin: #1 \group_end: } } % \end{macrocode} % \end{macro} % @@ -985,7 +1142,7 @@ % \testfile* % \begin{macrocode} \cs_new_protected:Npn \hbox_set:Nn #1#2 - { \tex_setbox:D #1 \tex_hbox:D {#2} } + { \tex_setbox:D #1 \tex_hbox:D { \group_begin: #2 \group_end: } } \cs_new_protected:Npn \hbox_gset:Nn { \tex_global:D \hbox_set:Nn } \cs_generate_variant:Nn \hbox_set:Nn { c } \cs_generate_variant:Nn \hbox_gset:Nn { c } @@ -999,7 +1156,10 @@ % Storing material in a horizontal box with a specified width. % \begin{macrocode} \cs_new_protected:Npn \hbox_set_to_wd:Nnn #1#2#3 - { \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:w #2 \__dim_eval_end: {#3} } + { + \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:w #2 \__dim_eval_end: + { \group_begin: #3 \group_end: } + } \cs_new_protected:Npn \hbox_gset_to_wd:Nnn { \tex_global:D \hbox_set_to_wd:Nnn } \cs_generate_variant:Nn \hbox_set_to_wd:Nnn { c } @@ -1016,13 +1176,21 @@ % environment definitions. % \begin{macrocode} \cs_new_protected:Npn \hbox_set:Nw #1 - { \tex_setbox:D #1 \tex_hbox:D \c_group_begin_token } + { + \tex_setbox:D #1 \tex_hbox:D + \c_group_begin_token + \group_begin: + } \cs_new_protected:Npn \hbox_gset:Nw { \tex_global:D \hbox_set:Nw } \cs_generate_variant:Nn \hbox_set:Nw { c } \cs_generate_variant:Nn \hbox_gset:Nw { c } -\cs_new_eq:NN \hbox_set_end: \c_group_end_token -\cs_new_eq:NN \hbox_gset_end: \c_group_end_token +\cs_new_protected:Npn \hbox_set_end: + { + \group_end: + \c_group_end_token + } +\cs_new_eq:NN \hbox_gset_end: \hbox_set_end: % \end{macrocode} % \end{macro} % \end{macro} @@ -1034,8 +1202,12 @@ % 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:w #1 \__dim_eval_end: {#2} } -\cs_new_protected:Npn \hbox_to_zero:n #1 { \tex_hbox:D to \c_zero_dim {#1} } + { + \tex_hbox:D to \__dim_eval:w #1 \__dim_eval_end: + { \group_begin: #2 \group_end: } + } +\cs_new_protected:Npn \hbox_to_zero:n #1 + { \tex_hbox:D to \c_zero_dim { \group_begin: #1 \group_end: } } % \end{macrocode} % \end{macro} % \end{macro} @@ -1076,8 +1248,10 @@ % \TestFiles{m3box003.lvt} % Put a vertical box directly into the input stream. % \begin{macrocode} -\cs_new_protected:Npn \vbox:n #1 { \tex_vbox:D { #1 \par } } -\cs_new_protected:Npn \vbox_top:n #1 { \tex_vtop:D { #1 \par } } +\cs_new_protected:Npn \vbox:n #1 + { \tex_vbox:D { \group_begin: #1 \par \group_end: } } +\cs_new_protected:Npn \vbox_top:n #1 + { \tex_vtop:D { \group_begin: #1 \par \group_end: } } % \end{macrocode} % \end{macro} % \end{macro} @@ -1088,9 +1262,15 @@ % 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:w #1 \__dim_eval_end: { #2 \par } } + { + \tex_vbox:D to \__dim_eval:w #1 \__dim_eval_end: + { \group_begin: #2 \par \group_end: } + } \cs_new_protected:Npn \vbox_to_zero:n #1 - { \tex_vbox:D to \c_zero_dim { #1 \par } } + { + \tex_vbox:D to \c_zero_dim + { \group_begin: #1 \par \group_end: } + } % \end{macrocode} % \end{macro} % \end{macro} @@ -1101,7 +1281,10 @@ % 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 { #2 \par } } + { + \tex_setbox:D #1 \tex_vbox:D + { \group_begin: #2 \par \group_end: } + } \cs_new_protected:Npn \vbox_gset:Nn { \tex_global:D \vbox_set:Nn } \cs_generate_variant:Nn \vbox_set:Nn { c } \cs_generate_variant:Nn \vbox_gset:Nn { c } @@ -1116,7 +1299,10 @@ % 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 { #2 \par } } + { + \tex_setbox:D #1 \tex_vtop:D + { \group_begin: #2 \par \group_end: } + } \cs_new_protected:Npn \vbox_gset_top:Nn { \tex_global:D \vbox_set_top:Nn } \cs_generate_variant:Nn \vbox_set_top:Nn { c } @@ -1133,7 +1319,7 @@ \cs_new_protected:Npn \vbox_set_to_ht:Nnn #1#2#3 { \tex_setbox:D #1 \tex_vbox:D to \__dim_eval:w #2 \__dim_eval_end: - { #3 \par } + { \group_begin: #3 \par \group_end: } } \cs_new_protected:Npn \vbox_gset_to_ht:Nnn { \tex_global:D \vbox_set_to_ht:Nnn } @@ -1151,14 +1337,19 @@ % environment definitions. % \begin{macrocode} \cs_new_protected:Npn \vbox_set:Nw #1 - { \tex_setbox:D #1 \tex_vbox:D \c_group_begin_token } + { + \tex_setbox:D #1 \tex_vbox:D + \c_group_begin_token + \group_begin: + } \cs_new_protected:Npn \vbox_gset:Nw { \tex_global:D \vbox_set:Nw } \cs_generate_variant:Nn \vbox_set:Nw { c } \cs_generate_variant:Nn \vbox_gset:Nw { c } \cs_new_protected:Npn \vbox_set_end: { - \par + \par + \group_end: \c_group_end_token } \cs_new_eq:NN \vbox_gset_end: \vbox_set_end: @@ -1189,6 +1380,550 @@ % \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} +% \begin{macro}[aux]{\@@_rotate:N} +% \begin{macro}[aux]{\@@_rotate_x:nnN, \@@_rotate_y:nnN} +% \begin{macro}[aux] +% { +% \@@_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 + { + \hbox_set:Nn #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 will +% always be 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:l3candidates: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:l3candidates: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 will be 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 + { + \tex_kern:D -\l_@@_left_new_dim + \hbox:n + { + \__driver_box_use_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: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_x: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_y: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_y:nnN \l_@@_right_dim \l_@@_top_dim + \l_@@_top_new_dim + \@@_rotate_y:nnN \l_@@_left_dim \l_@@_bottom_dim + \l_@@_bottom_new_dim + \@@_rotate_x:nnN \l_@@_left_dim \l_@@_top_dim + \l_@@_left_new_dim + \@@_rotate_x:nnN \l_@@_right_dim \l_@@_bottom_dim + \l_@@_right_new_dim + } +\cs_new_protected:Npn \@@_rotate_quadrant_two: + { + \@@_rotate_y:nnN \l_@@_right_dim \l_@@_bottom_dim + \l_@@_top_new_dim + \@@_rotate_y:nnN \l_@@_left_dim \l_@@_top_dim + \l_@@_bottom_new_dim + \@@_rotate_x:nnN \l_@@_right_dim \l_@@_top_dim + \l_@@_left_new_dim + \@@_rotate_x:nnN \l_@@_left_dim \l_@@_bottom_dim + \l_@@_right_new_dim + } +\cs_new_protected:Npn \@@_rotate_quadrant_three: + { + \@@_rotate_y:nnN \l_@@_left_dim \l_@@_bottom_dim + \l_@@_top_new_dim + \@@_rotate_y:nnN \l_@@_right_dim \l_@@_top_dim + \l_@@_bottom_new_dim + \@@_rotate_x:nnN \l_@@_right_dim \l_@@_bottom_dim + \l_@@_left_new_dim + \@@_rotate_x:nnN \l_@@_left_dim \l_@@_top_dim + \l_@@_right_new_dim + } +\cs_new_protected:Npn \@@_rotate_quadrant_four: + { + \@@_rotate_y:nnN \l_@@_left_dim \l_@@_top_dim + \l_@@_top_new_dim + \@@_rotate_y:nnN \l_@@_right_dim \l_@@_bottom_dim + \l_@@_bottom_new_dim + \@@_rotate_x:nnN \l_@@_left_dim \l_@@_bottom_dim + \l_@@_left_new_dim + \@@_rotate_x:nnN \l_@@_right_dim \l_@@_top_dim + \l_@@_right_new_dim + } +% \end{macrocode} +% \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} +% \begin{macro}[aux]{\@@_resize_set_corners:N} +% \begin{macro}[aux]{\@@_resize:N} +% \begin{macro}[aux]{\@@_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 + { + \hbox_set:Nn #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_generate_variant:Nn \box_resize_to_wd_and_ht_plus_dp:Nnn { c } +\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} +% +% \begin{macro}{\box_resize_to_ht:Nn, \box_resize_to_ht:cn} +% \begin{macro}{\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn} +% \begin{macro}{\box_resize_to_wd:Nn, \box_resize_to_wd:cn} +% \begin{macro}{\box_resize_to_wd_and_ht:Nnn, \box_resize_to_wd_and_ht:cnn} +% 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 + { + \hbox_set:Nn #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_generate_variant:Nn \box_resize_to_ht:Nn { c } +\cs_new_protected:Npn \box_resize_to_ht_plus_dp:Nn #1#2 + { + \hbox_set:Nn #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_generate_variant:Nn \box_resize_to_ht_plus_dp:Nn { c } +\cs_new_protected:Npn \box_resize_to_wd:Nn #1#2 + { + \hbox_set:Nn #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_generate_variant:Nn \box_resize_to_wd:Nn { c } +\cs_new_protected:Npn \box_resize_to_wd_and_ht:Nnn #1#2#3 + { + \hbox_set:Nn #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 + } + } +\cs_generate_variant:Nn \box_resize_to_wd_and_ht:Nnn { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\box_scale:Nnn, \box_scale:cnn} +% \begin{macro}[aux]{\@@_scale_aux: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 + { + \hbox_set:Nn #1 + { + \fp_set:Nn \l_@@_scale_x_fp {#2} + \fp_set:Nn \l_@@_scale_y_fp {#3} + \@@_scale_aux:N #1 + } + } +\cs_generate_variant:Nn \box_scale:Nnn { c } +\cs_new_protected:Npn \@@_scale_aux: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} +% +% \begin{macro} +% { +% \box_autosize_to_wd_and_ht:Nnn , +% \box_autosize_to_wd_and_ht:cnn , +% \box_autosize_to_wd_and_ht_plus_dp:cnn , +% \box_autosize_to_wd_and_ht_plus_dp:Nnn +% } +% \begin{macro}[aux]{\@@_autosize:Nnnn} +% 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:Nnnn #1 {#2} {#3} { \box_ht:N #1 } } +\cs_generate_variant:Nn \box_autosize_to_wd_and_ht:Nnn { c } +\cs_new_protected:Npn \box_autosize_to_wd_and_ht_plus_dp:Nnn #1#2#3 + { \@@_autosize:Nnnn #1 {#2} {#3} { \box_ht:N #1 + \box_dp:N #1 } } +\cs_generate_variant:Nn \box_autosize_to_wd_and_ht_plus_dp:Nnn { c } +\cs_new_protected:Npn \@@_autosize:Nnnn #1#2#3#4 + { + \hbox_set:Nn #1 + { + \fp_set:Nn \l_@@_scale_x_fp { ( #2 ) / \box_wd:N #1 } + \fp_set:Nn \l_@@_scale_y_fp { ( #3 ) / ( #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_aux:N #1 + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux]{\@@_resize_common:N} +% The main resize function places in input into a box which will start +% of 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 + { + \__driver_box_use_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 } + { + \tex_kern:D \l_@@_right_new_dim + \box_use:N \l_@@_internal_box + \tex_hss:D + } + } + { + \box_set_wd:Nn \l_@@_internal_box { \l_@@_right_new_dim } + \hbox:n + { + \tex_kern:D \c_zero_dim + \box_use:N \l_@@_internal_box + \tex_hss:D + } + } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Deprecated functions} +% +% \begin{macro}{\box_resize:Nnn, \box_resize:cnn} +% \begin{macrocode} +\cs_new_eq:NN \box_resize:Nnn \box_resize_to_wd_and_ht_plus_dp:Nnn +\cs_new_eq:NN \box_resize:cnn \box_resize_to_wd_and_ht_plus_dp:cnn +% \end{macrocode} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx index a96bc8c8f4e..627f4eba9e0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -84,125 +84,6 @@ % % \section{Additions to \pkg{l3box}} % -% \subsection{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}{\box_resize:Nnn, \box_resize:cnn} -% \begin{syntax} -% \cs{box_resize:Nnn} \meta{box} \Arg{x-size} \Arg{y-size} -% \end{syntax} -% Resize 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 vertical size (height plus depth) of -% the box. The updated \meta{box} will be an hbox, irrespective of the nature -% of the \meta{box} before the resizing is applied. Negative sizes will -% cause the material in the \meta{box} to be reversed in direction, but the -% reference point of the \meta{box} will be unchanged. -% Thus negative $y$-sizes will result in a box a depth dependent on the -% height of the original box a height dependent on the depth. -% The resizing applies within the current \TeX{} group level. -% \end{function} -% -% \begin{function} -% {\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn} -% \begin{syntax} -% \cs{box_resize_to_ht_plus_dp:Nn} \meta{box} \Arg{y-size} -% \end{syntax} -% Resize 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 vertical size (height plus depth) of -% the box. -% The updated \meta{box} will be an hbox, irrespective of the nature -% of the \meta{box} before the resizing is applied. A negative size will -% cause the material in the \meta{box} to be reversed in direction, but the -% reference point of the \meta{box} will be unchanged. -% Thus negative $y$-sizes will result in a box with depth dependent on the -% height of the original box and height dependent on the depth of the original. -% The resizing applies within the current \TeX{} group level. -% \end{function} -% -% \begin{function} -% {\box_resize_to_ht:Nn, \box_resize_to_ht:cn} -% \begin{syntax} -% \cs{box_resize_to_ht:Nn} \meta{box} \Arg{y-size} -% \end{syntax} -% Resize 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, not including depth, of -% the box. -% The updated \meta{box} will be an hbox, irrespective of the nature -% of the \meta{box} before the resizing is applied. -% A negative size will -% cause the material in the \meta{box} to be reversed in direction, but the -% reference point of the \meta{box} will be unchanged. -% Thus negative $y$-sizes will result in a box with depth dependent on the -% height of the original box and height dependent on the depth of the original. -% The resizing applies within the current \TeX{} group level. -% \end{function} -% -% \begin{function}{\box_resize_to_wd:Nn, \box_resize_to_wd:cn} -% \begin{syntax} -% \cs{box_resize_to_wd:Nn} \meta{box} \Arg{x-size} -% \end{syntax} -% Resize 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} will be an hbox, irrespective of the nature -% of the \meta{box} before the resizing is applied. A negative size will -% cause the material in the \meta{box} to be reversed in direction, but the -% reference point of the \meta{box} will be unchanged. -% Thus negative $y$-sizes will result in a box a depth dependent on the -% height of the original box a height dependent on the depth. -% The resizing applies within the current \TeX{} group level. -% \end{function} -% -% \begin{function}[added = 2014-07-03] -% {\box_resize_to_wd_and_ht:Nnn, \box_resize_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} -% Resize the \meta{box} to a \emph{height} of -% \meta{x-size} horizontally and \meta{y-size} -% vertically (both of the sizes are dimension expressions). -% The \meta{y-size} is the \emph{height} of the box, ignoring any depth. -% The updated \meta{box} will be an hbox, irrespective of the nature -% of the \meta{box} before the resizing is applied. Negative sizes will -% cause the material in the \meta{box} to be reversed in direction, but the -% reference point of the \meta{box} will be unchanged. -% \end{function} -% -% \begin{function}{\box_rotate:Nn, \box_rotate:cn} -% \begin{syntax} -% \cs{box_rotate:Nn} \meta{box} \Arg{angle} -% \end{syntax} -% Rotates the \meta{box} by \meta{angle} (in degrees) anti-clockwise about -% its reference point. The reference point of the updated box will be moved -% horizontally such that it is at the left side of the smallest rectangle -% enclosing the rotated material. -% The updated \meta{box} will be an hbox, irrespective of the nature -% of the \meta{box} before the rotation is applied. The rotation applies -% within the current \TeX{} group level. -% \end{function} -% -% \begin{function}{\box_scale:Nnn, \box_scale: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 -% integer expressions). The updated \meta{box} will be an hbox, irrespective -% of the nature of the \meta{box} before the scaling is applied. Negative -% scalings will cause the material in the \meta{box} to be reversed in -% direction, but the reference point of the \meta{box} will be unchanged. -% Thus negative $y$-scales will result in a box a depth dependent on the -% height of the original box a height dependent on the depth. -% The resizing applies within the current \TeX{} group level. -% \end{function} -% % \subsection{Viewing part of a box} % % \begin{function}{\box_clip:N, \box_clip:c} @@ -592,6 +473,39 @@ % warning message of some sort. % \end{function} % +% \section{Additions to \pkg{l3sys}} +% +% \begin{function}[added = 2017-04-12, EXP, pTF]{\sys_if_rand_exist:} +% \begin{syntax} +% \cs{sys_if_rand_exist_p:} +% \cs{sys_if_rand_exist:TF} \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if the engine has a pseudo-random number generator. Currently +% this is the case in \pdfTeX{} and \LuaTeX{}. +% \end{function} +% +% \begin{function}[added = 2017-04-12, EXP]{\sys_rand_seed:} +% \begin{syntax} +% \cs{sys_rand_seed:} +% \end{syntax} +% Expands to the current value of the engine's random seed, a +% non-negative integer. In engines without random number support this +% expands to $0$. +% \end{function} +% +% \begin{function}[added = 2017-04-12]{\sys_gset_rand_seed:n} +% \begin{syntax} +% \cs{sys_gset_rand_seed:n} \Arg{intexpr} +% \end{syntax} +% Sets the seed for the engine's pseudo-random number generator to the +% \meta{integer expression}. The assignment is global. This random +% seed affects all \cs[no-index]{\ldots{}_rand} functions (such as +% \cs{int_rand:nn} or \cs{clist_rand_item:n}) as well as other +% packages relying on the engine's random number generator. Currently +% only the absolute value of the seed is used. In engines without +% random number support this produces an error. +% \end{function} +% % \section{Additions to \pkg{l3tl}} % % \begin{function}[EXP,pTF]{\tl_if_single_token:n} @@ -947,515 +861,6 @@ %<@@=box> % \end{macrocode} % -% \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} -% \begin{macro}[aux]{\@@_rotate:N} -% \begin{macro}[aux]{\@@_rotate_x:nnN, \@@_rotate_y:nnN} -% \begin{macro}[aux] -% { -% \@@_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 - { - \hbox_set:Nn #1 - { - \group_begin: - \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 - \group_end: - } - } -% \end{macrocode} -% The edges of the box are then recorded: the left edge will -% always be 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:l3candidates: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:l3candidates: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 will be 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 - { - \tex_kern:D -\l_@@_left_new_dim - \hbox:n - { - \__driver_box_use_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: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_x: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_y: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_y:nnN \l_@@_right_dim \l_@@_top_dim - \l_@@_top_new_dim - \@@_rotate_y:nnN \l_@@_left_dim \l_@@_bottom_dim - \l_@@_bottom_new_dim - \@@_rotate_x:nnN \l_@@_left_dim \l_@@_top_dim - \l_@@_left_new_dim - \@@_rotate_x:nnN \l_@@_right_dim \l_@@_bottom_dim - \l_@@_right_new_dim - } -\cs_new_protected:Npn \@@_rotate_quadrant_two: - { - \@@_rotate_y:nnN \l_@@_right_dim \l_@@_bottom_dim - \l_@@_top_new_dim - \@@_rotate_y:nnN \l_@@_left_dim \l_@@_top_dim - \l_@@_bottom_new_dim - \@@_rotate_x:nnN \l_@@_right_dim \l_@@_top_dim - \l_@@_left_new_dim - \@@_rotate_x:nnN \l_@@_left_dim \l_@@_bottom_dim - \l_@@_right_new_dim - } -\cs_new_protected:Npn \@@_rotate_quadrant_three: - { - \@@_rotate_y:nnN \l_@@_left_dim \l_@@_bottom_dim - \l_@@_top_new_dim - \@@_rotate_y:nnN \l_@@_right_dim \l_@@_top_dim - \l_@@_bottom_new_dim - \@@_rotate_x:nnN \l_@@_right_dim \l_@@_bottom_dim - \l_@@_left_new_dim - \@@_rotate_x:nnN \l_@@_left_dim \l_@@_top_dim - \l_@@_right_new_dim - } -\cs_new_protected:Npn \@@_rotate_quadrant_four: - { - \@@_rotate_y:nnN \l_@@_left_dim \l_@@_top_dim - \l_@@_top_new_dim - \@@_rotate_y:nnN \l_@@_right_dim \l_@@_bottom_dim - \l_@@_bottom_new_dim - \@@_rotate_x:nnN \l_@@_left_dim \l_@@_bottom_dim - \l_@@_left_new_dim - \@@_rotate_x:nnN \l_@@_right_dim \l_@@_top_dim - \l_@@_right_new_dim - } -% \end{macrocode} -% \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:Nnn, \box_resize:cnn} -% \begin{macro}[aux]{\@@_resize_set_corners:N} -% \begin{macro}[aux]{\@@_resize:N} -% \begin{macro}[aux]{\@@_resize:NNN} -% Resizing a box starts by working out the various dimensions of the -% existing box. -% \begin{macrocode} -\cs_new_protected:Npn \box_resize:Nnn #1#2#3 - { - \hbox_set:Nn #1 - { - \group_begin: - \@@_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 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize:Nnn { c } -\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} -% -% \begin{macro}{\box_resize_to_ht:Nn, \box_resize_to_ht:cn} -% \begin{macro}{\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn} -% \begin{macro}{\box_resize_to_wd:Nn, \box_resize_to_wd:cn} -% \begin{macro}{\box_resize_to_wd_and_ht:Nnn, \box_resize_to_wd_and_ht:cnn} -% 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 - { - \hbox_set:Nn #1 - { - \group_begin: - \@@_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 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize_to_ht:Nn { c } -\cs_new_protected:Npn \box_resize_to_ht_plus_dp:Nn #1#2 - { - \hbox_set:Nn #1 - { - \group_begin: - \@@_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 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize_to_ht_plus_dp:Nn { c } -\cs_new_protected:Npn \box_resize_to_wd:Nn #1#2 - { - \hbox_set:Nn #1 - { - \group_begin: - \@@_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 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize_to_wd:Nn { c } -\cs_new_protected:Npn \box_resize_to_wd_and_ht:Nnn #1#2#3 - { - \hbox_set:Nn #1 - { - \group_begin: - \@@_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 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize_to_wd_and_ht:Nnn { c } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\box_scale:Nnn, \box_scale:cnn} -% 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 dimension scaling operations are carried out using -% the \TeX{} mechanism as it avoids needing to use too many \texttt{fp} -% operations. -% \begin{macrocode} -\cs_new_protected:Npn \box_scale:Nnn #1#2#3 - { - \hbox_set:Nn #1 - { - \group_begin: - \fp_set:Nn \l_@@_scale_x_fp {#2} - \fp_set:Nn \l_@@_scale_y_fp {#3} - \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 - \group_end: - } - } -\cs_generate_variant:Nn \box_scale:Nnn { c } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[aux]{\@@_resize_common:N} -% The main resize function places in input into a box which will start -% of 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 - { - \__driver_box_use_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 } - { - \tex_kern:D \l_@@_right_new_dim - \box_use:N \l_@@_internal_box - \tex_hss:D - } - } - { - \box_set_wd:Nn \l_@@_internal_box { \l_@@_right_new_dim } - \hbox:n - { - \tex_kern:D \c_zero_dim - \box_use:N \l_@@_internal_box - \tex_hss:D - } - } - } -% \end{macrocode} -% \end{macro} -% % \subsection{Viewing part of a box} % % \begin{macro}{\box_clip:N, \box_clip:c} @@ -1960,7 +1365,7 @@ \dim_to_fp:n {#3} / \dim_to_fp:n { \coffin_ht:N #1 + \coffin_dp:N #1 } } - \box_resize:Nnn #1 {#2} {#3} + \box_resize_to_wd_and_ht_plus_dp:Nnn #1 {#2} {#3} \@@_resize_common:Nnn #1 {#2} {#3} } \cs_generate_variant:Nn \coffin_resize:Nnn { c } @@ -2142,8 +1547,8 @@ % Mapping to an input stream can be done on either a token or a string % basis, hence the set up. Within that, there is a check to avoid reading % past the end of a file, hence the two applications of \cs{ior_if_eof:N}. -% This mapping cannot be nested as the stream has only one \enquote{current -% line}. +% This mapping cannot be nested with twice the same stream, as the +% stream has only one \enquote{current line}. % \begin{macrocode} \cs_new_protected:Npn \ior_map_inline:Nn { \@@_map_inline:NNn \ior_get:NN } @@ -2157,7 +1562,7 @@ } \cs_new_protected:Npn \@@_map_inline:NNNn #1#2#3#4 { - \cs_set:Npn #1 ##1 {#4} + \cs_gset_protected:Npn #1 ##1 {#4} \ior_if_eof:NF #3 { \@@_map_inline_loop:NNN #1#2#3 } \__prg_break_point:Nn \ior_map_break: { \int_gdecr:N \g__prg_map_int } @@ -2567,9 +1972,41 @@ } } % \end{macrocode} -% \end{macro} +% \end{macro} +% +% \subsection{Additions to \pkg{l3sys}} +% +% \begin{macro}[EXP, pTF]{\sys_if_rand_exist:} +% Currently, randomness exists under \pdfTeX{} and \LuaTeX{}. +% \begin{macrocode} +\cs_if_exist:NTF \pdftex_uniformdeviate:D + { + \prg_new_conditional:Npnn \sys_if_rand_exist: { p , T , F , TF } + { \prg_return_true: } + } + { + \prg_new_conditional:Npnn \sys_if_rand_exist: { p , T , F , TF } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} % -% \subsection{Additions to \pkg{l3tl}} +% \begin{macro}[EXP]{\sys_rand_seed:} +% Unpack the primitive. +% \begin{macrocode} +\cs_new:Npn \sys_rand_seed: { \tex_the:D \pdftex_randomseed:D } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sys_gset_rand_seed:n} +% The primitive always assigns the seed globally. +% \begin{macrocode} +\cs_new_protected:Npn \sys_gset_rand_seed:n #1 + { \pdftex_setrandomseed:D \__int_eval:w #1 \__int_eval_end: } +% \end{macrocode} +% \end{macro} +% +% \subsection{Additions to \pkg{l3tl}} % % \begin{macrocode} %<@@=tl> @@ -3697,10 +3134,9 @@ % octets, so that is taken as read. % \begin{macrocode} \group_begin: - \bool_if:nT - { - \sys_if_engine_pdftex_p: || \sys_if_engine_uptex_p: - } + \bool_lazy_or:nnT + { \sys_if_engine_pdftex_p: } + { \sys_if_engine_uptex_p: } { \cs_set_protected:Npn \@@_loop:nn #1#2 { diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx index dd0ba51b688..4876e488bd3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -1553,7 +1553,8 @@ \clist_if_empty:NF #1 { \int_gincr:N \g__prg_map_int - \cs_gset:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} + \cs_gset_protected:cpn + { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} \exp_last_unbraced:Nco \@@_map_function:Nw { __prg_map_ \int_use:N \g__prg_map_int :w } #1 , \q_recursion_tail , diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx index 278bbf199b5..1bc70605f7b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -359,10 +359,10 @@ % place, of course. % \begin{macrocode} \prop_new:N \c_@@_corners_prop -\prop_put:Nnn \c_@@_corners_prop { tl } { { 0 pt } { 0 pt } } -\prop_put:Nnn \c_@@_corners_prop { tr } { { 0 pt } { 0 pt } } -\prop_put:Nnn \c_@@_corners_prop { bl } { { 0 pt } { 0 pt } } -\prop_put:Nnn \c_@@_corners_prop { br } { { 0 pt } { 0 pt } } +\prop_put:Nnn \c_@@_corners_prop { tl } { { 0pt } { 0pt } } +\prop_put:Nnn \c_@@_corners_prop { tr } { { 0pt } { 0pt } } +\prop_put:Nnn \c_@@_corners_prop { bl } { { 0pt } { 0pt } } +\prop_put:Nnn \c_@@_corners_prop { br } { { 0pt } { 0pt } } % \end{macrocode} % \end{variable} % @@ -371,11 +371,11 @@ % based values. % \begin{macrocode} \prop_new:N \c_@@_poles_prop -\tl_set:Nn \l_@@_internal_tl { { 0 pt } { 0 pt } { 0 pt } { 1000 pt } } +\tl_set:Nn \l_@@_internal_tl { { 0pt } { 0pt } { 0pt } { 1000pt } } \prop_put:Nno \c_@@_poles_prop { l } { \l_@@_internal_tl } \prop_put:Nno \c_@@_poles_prop { hc } { \l_@@_internal_tl } \prop_put:Nno \c_@@_poles_prop { r } { \l_@@_internal_tl } -\tl_set:Nn \l_@@_internal_tl { { 0 pt } { 0 pt } { 1000 pt } { 0 pt } } +\tl_set:Nn \l_@@_internal_tl { { 0pt } { 0pt } { 1000pt } { 0pt } } \prop_put:Nno \c_@@_poles_prop { b } { \l_@@_internal_tl } \prop_put:Nno \c_@@_poles_prop { vc } { \l_@@_internal_tl } \prop_put:Nno \c_@@_poles_prop { t } { \l_@@_internal_tl } @@ -535,10 +535,8 @@ { \hbox_set:Nn #1 { - \color_group_begin: - \color_ensure_current: - #2 - \color_group_end: + \color_ensure_current: + #2 } \@@_reset_structure:N #1 \@@_update_poles:N #1 @@ -569,9 +567,7 @@ \dim_set_eq:NN \linewidth \tex_hsize:D \dim_set_eq:NN \columnwidth \tex_hsize:D %</package> - \color_group_begin: - #3 - \color_group_end: + #3 } \@@_reset_structure:N #1 \@@_update_poles:N #1 @@ -579,13 +575,13 @@ \vbox_set_top:Nn \l_@@_internal_box { \vbox_unpack:N #1 } \@@_set_pole:Nnx #1 { T } { - { 0 pt } + { 0pt } { \dim_eval:n { \box_ht:N #1 - \box_ht:N \l_@@_internal_box } } - { 1000 pt } - { 0 pt } + { 1000pt } + { 0pt } } \box_clear:N \l_@@_internal_box } @@ -603,10 +599,9 @@ { \@@_if_exist:NT #1 { - \hbox_set:Nw #1 \color_group_begin: \color_ensure_current: + \hbox_set:Nw #1 \color_ensure_current: \cs_set_protected:Npn \hcoffin_set_end: { - \color_group_end: \hbox_set_end: \@@_reset_structure:N #1 \@@_update_poles:N #1 @@ -634,10 +629,8 @@ \dim_set_eq:NN \linewidth \tex_hsize:D \dim_set_eq:NN \columnwidth \tex_hsize:D %</package> - \color_group_begin: \cs_set_protected:Npn \vcoffin_set_end: { - \color_group_end: \vbox_set_end: \@@_reset_structure:N #1 \@@_update_poles:N #1 @@ -645,13 +638,13 @@ \vbox_set_top:Nn \l_@@_internal_box { \vbox_unpack:N #1 } \@@_set_pole:Nnx #1 { T } { - { 0 pt } + { 0pt } { \dim_eval:n { \box_ht:N #1 - \box_ht:N \l_@@_internal_box } } - { 1000 pt } - { 0 pt } + { 1000pt } + { 0pt } } \box_clear:N \l_@@_internal_box } @@ -738,7 +731,7 @@ { \__msg_kernel_error:nnxx { kernel } { unknown-coffin-pole } {#2} { \token_to_str:N #1 } - \tl_set:Nn #3 { { 0 pt } { 0 pt } { 0 pt } { 0 pt } } + \tl_set:Nn #3 { { 0pt } { 0pt } { 0pt } { 0pt } } } } % \end{macrocode} @@ -793,8 +786,8 @@ { \@@_set_pole:Nnx #1 {#2} { - { 0 pt } { \dim_eval:n {#3} } - { 1000 pt } { 0 pt } + { 0pt } { \dim_eval:n {#3} } + { 1000pt } { 0pt } } } } @@ -804,8 +797,8 @@ { \@@_set_pole:Nnx #1 {#2} { - { \dim_eval:n {#3} } { 0 pt } - { 0 pt } { 1000 pt } + { \dim_eval:n {#3} } { 0pt } + { 0pt } { 1000pt } } } } @@ -827,11 +820,11 @@ \cs_new_protected:Npn \@@_update_corners:N #1 { \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } { tl } - { { 0 pt } { \dim_eval:n { \box_ht:N #1 } } } + { { 0pt } { \dim_eval:n { \box_ht:N #1 } } } \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } { tr } { { \dim_eval:n { \box_wd:N #1 } } { \dim_eval:n { \box_ht:N #1 } } } \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } { bl } - { { 0 pt } { \dim_eval:n { - \box_dp:N #1 } } } + { { 0pt } { \dim_eval:n { -\box_dp:N #1 } } } \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } { br } { { \dim_eval:n { \box_wd:N #1 } } { \dim_eval:n { -\box_dp:N #1 } } } } @@ -850,33 +843,33 @@ \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { hc } { { \dim_eval:n { 0.5 \box_wd:N #1 } } - { 0 pt } { 0 pt } { 1000 pt } + { 0pt } { 0pt } { 1000pt } } \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { r } { { \dim_eval:n { \box_wd:N #1 } } - { 0 pt } { 0 pt } { 1000 pt } + { 0pt } { 0pt } { 1000pt } } \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { vc } { - { 0 pt } + { 0pt } { \dim_eval:n { ( \box_ht:N #1 - \box_dp:N #1 ) / 2 } } - { 1000 pt } - { 0 pt } + { 1000pt } + { 0pt } } \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { t } { - { 0 pt } + { 0pt } { \dim_eval:n { \box_ht:N #1 } } - { 1000 pt } - { 0 pt } + { 1000pt } + { 0pt } } \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { b } { - { 0 pt } - { \dim_eval:n { - \box_dp:N #1 } } - { 1000 pt } - { 0 pt } + { 0pt } + { \dim_eval:n { -\box_dp:N #1 } } + { 1000pt } + { 0pt } } } % \end{macrocode} @@ -1116,9 +1109,9 @@ % those from the two parent coffins are needed. % \begin{macrocode} \@@_reset_structure:N \l_@@_aligned_coffin - \prop_clear:c - { l_@@_corners_ \__int_value:w \l_@@_aligned_coffin _ prop } - \@@_update_poles:N \l_@@_aligned_coffin + \prop_clear:c + { l_@@_corners_ \__int_value:w \l_@@_aligned_coffin _ prop } + \@@_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 @@ -1126,16 +1119,16 @@ % \begin{macrocode} \dim_compare:nNnTF \l_@@_offset_x_dim < \c_zero_dim { - \@@_offset_poles:Nnn #1 { -\l_@@_offset_x_dim } { 0 pt } - \@@_offset_poles:Nnn #4 { 0 pt } { \l_@@_offset_y_dim } - \@@_offset_corners:Nnn #1 { -\l_@@_offset_x_dim } { 0 pt } - \@@_offset_corners:Nnn #4 { 0 pt } { \l_@@_offset_y_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 { 0 pt } { 0 pt } + \@@_offset_poles:Nnn #1 { 0pt } { 0pt } \@@_offset_poles:Nnn #4 { \l_@@_offset_x_dim } { \l_@@_offset_y_dim } - \@@_offset_corners:Nnn #1 { 0 pt } { 0 pt } + \@@_offset_corners:Nnn #1 { 0pt } { 0pt } \@@_offset_corners:Nnn #4 { \l_@@_offset_x_dim } { \l_@@_offset_y_dim } } @@ -1170,7 +1163,7 @@ { l_@@_corners_ \__int_value:w \l_@@_aligned_coffin _prop } { l_@@_corners_ \__int_value:w #1 _prop } \@@_update_poles:N \l_@@_aligned_coffin - \@@_offset_poles:Nnn #1 { 0 pt } { 0 pt } + \@@_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 @@ -1307,11 +1300,11 @@ \dim_compare:nNnTF {#2} < {#6} { \@@_set_pole:Nnx #9 { T } - { { 0 pt } {#6} { 1000 pt } { 0 pt } } + { { 0pt } {#6} { 1000pt } { 0pt } } } { \@@_set_pole:Nnx #9 { T } - { { 0 pt } {#2} { 1000 pt } { 0 pt } } + { { 0pt } {#2} { 1000pt } { 0pt } } } } \cs_new_protected:Npn \@@_update_B:nnnnnnnnN #1#2#3#4#5#6#7#8#9 @@ -1319,11 +1312,11 @@ \dim_compare:nNnTF {#2} < {#6} { \@@_set_pole:Nnx #9 { B } - { { 0 pt } {#2} { 1000 pt } { 0 pt } } + { { 0pt } {#2} { 1000pt } { 0pt } } } { \@@_set_pole:Nnx #9 { B } - { { 0 pt } {#6} { 1000 pt } { 0 pt } } + { { 0pt } {#6} { 1000pt } { 0pt } } } } % \end{macrocode} @@ -1412,7 +1405,7 @@ % displaying handles. % \begin{macrocode} \dim_new:N \l_@@_display_offset_dim -\dim_set:Nn \l_@@_display_offset_dim { 2 pt } +\dim_set:Nn \l_@@_display_offset_dim { 2pt } % \end{macrocode} % \end{variable} % @@ -1463,15 +1456,15 @@ \hcoffin_set:Nn \l_@@_display_pole_coffin { %<*initex> - \hbox:n { \tex_vrule:D width 1 pt height 1 pt \scan_stop: } % TODO + \hbox:n { \tex_vrule:D width 1pt height 1pt \scan_stop: } % TODO %</initex> %<*package> \color {#4} - \rule { 1 pt } { 1 pt } + \rule { 1pt } { 1pt } %</package> } \coffin_attach_mark:NnnNnnnn #1 {#2} {#3} - \l_@@_display_pole_coffin { hc } { vc } { 0 pt } { 0 pt } + \l_@@_display_pole_coffin { hc } { vc } { 0pt } { 0pt } \hcoffin_set:Nn \l_@@_display_coord_coffin { %<*initex> @@ -1493,7 +1486,7 @@ { \coffin_attach_mark:NnnNnnnn #1 {#2} {#3} \l_@@_display_coord_coffin { l } { vc } - { 1 pt } { 0 pt } + { 1pt } { 0pt } } { \exp_last_unbraced:No \@@_mark_handle_aux:nnnnNnn @@ -1532,11 +1525,11 @@ \hcoffin_set:Nn \l_@@_display_pole_coffin { %<*initex> - \hbox:n { \tex_vrule:D width 1 pt height 1 pt \scan_stop: } % TODO + \hbox:n { \tex_vrule:D width 1pt height 1pt \scan_stop: } % TODO %</initex> %<*package> \color {#2} - \rule { 1 pt } { 1 pt } + \rule { 1pt } { 1pt } %</package> } \prop_set_eq:Nc \l_@@_display_poles_prop @@ -1574,7 +1567,7 @@ \dim_set:Nn \l_@@_display_y_dim { \l_@@_y_dim } \@@_display_attach:Nnnnn \l_@@_display_pole_coffin { hc } { vc } - { 0 pt } { 0 pt } + { 0pt } { 0pt } \hcoffin_set:Nn \l_@@_display_coord_coffin { %<*initex> @@ -1596,7 +1589,7 @@ { \@@_display_attach:Nnnnn \l_@@_display_coord_coffin { l } { vc } - { 1 pt } { 0 pt } + { 1pt } { 0pt } } { \exp_last_unbraced:No diff --git a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx index e6631c63283..72bca5f43db 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -94,7 +94,7 @@ \cs_new_eq:NN \color_group_begin: \group_begin: \cs_new_protected:Npn \color_group_end: { - \tex_par:D + \par \group_end: } % \end{macrocode} @@ -104,33 +104,8 @@ % A driver-independent wrapper for setting the foreground color to the % current color \enquote{now}. % \begin{macrocode} -%<*initex> \cs_new_protected:Npn \color_ensure_current: { \__driver_color_ensure_current: } -%</initex> -% \end{macrocode} -% In package mode, the driver code may not be loaded. To keep down -% dependencies, if there is no driver code available and no \cs{set@color} -% then color is not in use and this function can be a no-op. -% \begin{macrocode} -%<*package> -\cs_new_protected:Npn \color_ensure_current: { } -\AtBeginDocument - { - \cs_if_exist:NTF \__driver_color_ensure_current: - { - \cs_set_protected:Npn \color_ensure_current: - { \__driver_color_ensure_current: } - } - { - \cs_if_exist:NT \set@color - { - \cs_set_protected:Npn \color_ensure_current: - { \set@color } - } - } - } -%</package> % \end{macrocode} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx index 1f8c208d618..d1eaba62294 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -140,6 +140,8 @@ \@@_error:Nnn \tl_to_lowercase:n { } { 2017-12-31 } \@@_error:Nnn \tl_to_uppercase:n { } { 2017-12-31 } \@@_error:Nnn \ior_get_str:NN { \ior_str_get:NN } { 2017-12-31 } + \@@_error:Nnn \box_resize:Nnn { \box_resize_to_wd_and_ht_plus_dp:Nnn } { 2018-12-31 } + \@@_error:Nnn \box_resize:cnn { \box_resize_to_wd_and_ht_plus_dp:cnn } { 2018-12-31 } \@@_error:Nnn \c_minus_one { - 1 } { 2018-12-31 } \@@_error:Nnn \sort_ordered: { \sort_return_same: } { 2018-12-31 } \@@_error:Nnn \sort_reversed: { \sort_return_swapped: } { 2018-12-31 } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx index 464320e84a1..516925b3e4a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx @@ -70,14 +70,14 @@ and all files in that bundle must be distributed together. % This isn't included in the typeset documentation because it's a bit % ugly: %<*class> -\ProvidesExplClass{l3doc}{2017/04/01}{} +\ProvidesExplClass{l3doc}{2017/05/13}{} {L3 Experimental documentation class} %</class> % \fi % % \title{The \cls{l3doc} class} % \author{\Team} -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % \maketitle % \tableofcontents % @@ -2254,7 +2254,7 @@ and all files in that bundle must be distributed together. \clist_clear:N \l_@@_function_label_clist \tl_set:Nn \l_@@_override_module_tl { \q_no_value } \char_set_catcode_active:N \< - \cs_set_protected:Npn < ##1 > { \meta {##1} } + \cs_set_protected_nopar:Npn < ##1 > { \meta {##1} } } \group_end: % \end{macrocode} @@ -4370,5 +4370,3 @@ page_precedence "rnaA" % \end{implementation} % % \PrintIndex -% -% \endinput diff --git a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx index dbcc32eac12..4f8ec457518 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx @@ -61,7 +61,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx index 94f7d3ccd03..9584a9aa624 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx @@ -45,7 +45,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -64,8 +64,8 @@ % \item \texttt{dvipdfmx}: The \texttt{dvipdfmx} program, which works in % conjugation with \pdfTeX{} or \LuaTeX{} in DVI mode. % \item \texttt{dvisvgm}: The \texttt{dvisvgm} program, which works in -% conjugation with \pdfTeX{} or \LuaTeX{} in DVI mode to create SVG -% output. +% conjugation with \pdfTeX{} or \LuaTeX{} when run in DVI mode as well +% as with (u)p\TeX{} and \XeTeX{}. % \item \texttt{xdvipdfmx}: The driver used by \XeTeX{}. % \end{itemize} % @@ -551,6 +551,93 @@ % \end{macrocode} % \end{macro} % +% \subsubsection{Box operations} +% +% \begin{macro}{\@@_box_use_clip:N} +% The general method is to save the current location, define a clipping path +% equivalent to the bounding box, then insert the content at the current +% position and in a zero width box. The \enquote{real} width is then made up +% using a horizontal skip before tidying up. There are other approaches that +% can be taken (for example using XForm objects), but the logic here shares +% as much code as possible and uses the same conversions (and so same +% rounding errors) in all cases. +% \begin{macrocode} +\cs_new_protected:Npn \@@_box_use_clip:N #1 + { + \@@_scope_begin: + \@@_literal:n + { + 0~ + \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } + \hbox_overlap_right:n { \box_use:N #1 } + \@@_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@@_box_use_rotate:Nn} +% \begin{variable}{\l_@@_cos_fp, \l_@@_sin_fp} +% Rotations are set using an affine transformation matrix which therefore +% requires sine/cosine values not the angle itself. We store the rounded +% values to avoid rounding twice. There are also a couple of comparisons to +% ensure that |-0| is not written to the output, as this avoids any issues +% with problematic display programs. Note that numbers are compared to~$0$ +% after rounding. +% \begin{macrocode} +\cs_new_protected:Npn \@@_box_use_rotate:Nn #1#2 + { + \@@_scope_begin: + \box_set_wd:Nn #1 \c_zero_dim + \fp_set:Nn \l_@@_cos_fp { round ( cosd ( #2 ) , 5 ) } + \fp_compare:nNnT \l_@@_cos_fp = \c_zero_fp + { \fp_zero:N \l_@@_cos_fp } + \fp_set:Nn \l_@@_sin_fp { round ( sind ( #2 ) , 5 ) } + \@@_matrix:n + { + \fp_use:N \l_@@_cos_fp \c_space_tl + \fp_compare:nNnTF \l_@@_sin_fp = \c_zero_fp + { 0~0 } + { + \fp_use:N \l_@@_sin_fp + \c_space_tl + \fp_eval:n { -\l_@@_sin_fp } + } + \c_space_tl + \fp_use:N \l_@@_cos_fp + } + \box_use:N #1 + \@@_scope_end: + } +\fp_new:N \l_@@_cos_fp +\fp_new:N \l_@@_sin_fp +% \end{macrocode} +% \end{variable} +% \end{macro} +% +% \begin{macro}{\@@_box_use_scale:Nnn} +% The same idea as for rotation but without the complexity of signs and +% cosines. +% \begin{macrocode} +\cs_new_protected:Npn \@@_box_use_scale:Nnn #1#2#3 + { + \@@_scope_begin: + \@@_matrix:n + { + \fp_eval:n { round ( #2 , 5 ) } ~ + 0~0~ + \fp_eval:n { round ( #3 , 5 ) } + } + \hbox_overlap_right:n { \box_use:N #1 } + \@@_scope_end: + } +% \end{macrocode} +% \end{macro} +% % \subsubsection{Color} % % \begin{variable}{\l_@@_current_color_tl} @@ -623,7 +710,9 @@ % % \begin{macro}[int]{\@@_literal:n} % Equivalent to \texttt{pdf:content} but favored as the link to -% the \pdfTeX{} primitive approach is clearer. +% the \pdfTeX{} primitive approach is clearer. Some higher-level operations +% use |\tex_special:D| directly: see the later comments on where this is +% useful. % \begin{macrocode} \cs_new_protected:Npn \@@_literal:n #1 { \tex_special:D { pdf:literal~ #1 } } @@ -631,22 +720,80 @@ % \end{macro} % % \begin{macro}[int]{\@@_scope_begin:, \@@_scope_end:} -% Scoping is done using direct PDF operations here. +% Scoping is done using the driver-specific specials. % \begin{macrocode} \cs_new_protected:Npn \@@_scope_begin: - { \@@_literal:n { q } } + { \tex_special:D { x:gsave } } \cs_new_protected:Npn \@@_scope_end: - { \@@_literal:n { Q } } + { \tex_special:D { x:grestore } } % \end{macrocode} % \end{macro} % -% \begin{macro}[int]{\@@_matrix:n} -% With \texttt{(x)dvipdfmx} the matrix has to include a translation -% part: that is always zero and so is built in here so that the same -% internal interface works for all PDF-related drivers. +% \subsubsection{Box operations} +% +% \begin{macro}{\@@_box_use_clip:N} +% The code here is idential to that for \texttt{pdfmode}: unlike rotation and +% scaling, there is no higher-level support in the driver for clipping. % \begin{macrocode} -\cs_new_protected:Npn \@@_matrix:n #1 - { \@@_literal:n { #1 \c_space_tl 0~0~cm } } +\cs_new_protected:Npn \@@_box_use_clip:N #1 + { + \@@_scope_begin: + \@@_literal:n + { + 0~ + \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ + \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ + re~W~n + } + \hbox_overlap_right:n { \box_use:N #1 } + \@@_scope_end: + \skip_horizontal:n { \box_wd:N #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@@_box_use_rotate:Nn} +% Rotating in \texttt{(x)}dvipdmfx can be implemented using either PDF or +% driver-specific code. The former approach however is not \enquote{aware} +% of the content of boxes: this means that any links embded will not be +% adjusted by the rotation. As such, the driver-native approach is prefered: +% the code therefore is similar (though not identical) to the \texttt{dvips} +% version (notice the rotation angle here is positive). As for +% \texttt{dvips}, zero rotation is written as |0| not |-0|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_box_use_rotate:Nn #1#2 + { + \@@_scope_begin: + \tex_special:D + { + x:rotate~ + \fp_compare:nNnTF {#2} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( #2 , 5 ) } } + } + \box_use:N #1 + \@@_scope_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_box_use_scale:Nnn} +% Much the same idea for scaling: use the higher-level driver operation to allow +% for box content. +% \begin{macrocode} +\cs_new_protected:Npn \@@_box_use_scale:Nnn #1#2#3 + { + \@@_scope_begin: + \tex_special:D + { + x:scale~ + \fp_eval:n { round ( #2 , 5 ) } ~ + \fp_eval:n { round ( #3 , 5 ) } + } + \hbox_overlap_right:n { \box_use:N #1 } + \@@_scope_end: + } % \end{macrocode} % \end{macro} % @@ -724,103 +871,15 @@ %</xdvipdfmx> % \end{macrocode} % -% \subsection{Common code for PDF production} +% \subsection{Drawing commands: \texttt{pdfmode} and \texttt{(x)dvipdfmx}} % -% As all of the drivers which understand PDF-targeted specials act in much -% the same way there is a lot of shared code. Rather than try to DocStrip it -% interspersed with the above, we collect all of it here. +% Both \texttt{pdfmode} and \texttt{(x)dvipdfmx} directly produce PDF output +% and undertand a shared set of specials for drawing commands. % % \begin{macrocode} %<*dvipdfmx|pdfmode|xdvipdfmx> % \end{macrocode} % -% \subsubsection{Box operations} -% -% \begin{macro}{\@@_box_use_clip:N} -% The general method is to save the current location, define a clipping path -% equivalent to the bounding box, then insert the content at the current -% position and in a zero width box. The \enquote{real} width is then made up -% using a horizontal skip before tidying up. There are other approaches that -% can be taken (for example using XForm objects), but the logic here shares -% as much code as possible and uses the same conversions (and so same -% rounding errors) in all cases. -% \begin{macrocode} -\cs_new_protected:Npn \@@_box_use_clip:N #1 - { - \@@_scope_begin: - \@@_literal:n - { - 0~ - \dim_to_decimal_in_bp:n { -\box_dp:N #1 } ~ - \dim_to_decimal_in_bp:n { \box_wd:N #1 } ~ - \dim_to_decimal_in_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~ - re~W~n - } - \hbox_overlap_right:n { \box_use:N #1 } - \@@_scope_end: - \skip_horizontal:n { \box_wd:N #1 } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[int]{\@@_box_use_rotate:Nn} -% \begin{variable}{\l_@@_cos_fp, \l_@@_sin_fp} -% Rotations are set using an affine transformation matrix which therefore -% requires sine/cosine values not the angle itself. We store the rounded -% values to avoid rounding twice. There are also a couple of comparisons to -% ensure that |-0| is not written to the output, as this avoids any issues -% with problematic display programs. Note that numbers are compared to~$0$ -% after rounding. -% \begin{macrocode} -\cs_new_protected:Npn \@@_box_use_rotate:Nn #1#2 - { - \@@_scope_begin: - \box_set_wd:Nn #1 \c_zero_dim - \fp_set:Nn \l_@@_cos_fp { round ( cosd ( #2 ) , 5 ) } - \fp_compare:nNnT \l_@@_cos_fp = \c_zero_fp - { \fp_zero:N \l_@@_cos_fp } - \fp_set:Nn \l_@@_sin_fp { round ( sind ( #2 ) , 5 ) } - \@@_matrix:n - { - \fp_use:N \l_@@_cos_fp \c_space_tl - \fp_compare:nNnTF \l_@@_sin_fp = \c_zero_fp - { 0~0 } - { - \fp_use:N \l_@@_sin_fp - \c_space_tl - \fp_eval:n { -\l_@@_sin_fp } - } - \c_space_tl - \fp_use:N \l_@@_cos_fp - } - \box_use:N #1 - \@@_scope_end: - } -\fp_new:N \l_@@_cos_fp -\fp_new:N \l_@@_sin_fp -% \end{macrocode} -% \end{variable} -% \end{macro} -% -% \begin{macro}{\@@_box_use_scale:Nnn} -% The same idea as for rotation but without the complexity of signs and -% cosines. -% \begin{macrocode} -\cs_new_protected:Npn \@@_box_use_scale:Nnn #1#2#3 - { - \@@_scope_begin: - \@@_matrix:n - { - \fp_eval:n { round ( #2 , 5 ) } ~ - 0~0~ - \fp_eval:n { round ( #3 , 5 ) } - } - \hbox_overlap_right:n { \box_use:N #1 } - \@@_scope_end: - } -% \end{macrocode} -% \end{macro} -% % \subsection{Drawing} % % \begin{macro}[aux]{\@@_draw_literal:n, \@@_draw_literal:x} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx index fb54e04ad68..6908c0bc050 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx index 7422b8ccf8c..12ffc79a8c5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx index 79363feca39..2c25386e920 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -98,11 +98,9 @@ % (The primitives have to be available at point of use not just at point of % definition so a compatibility layer is hard to arrange here.) % \begin{macrocode} -\bool_if:nTF - { - \sys_if_engine_luatex_p: - || \sys_if_engine_xetex_p: - } +\bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } % \end{macrocode} % Unicode engines: make these two invalid (this happens after \TeX{} % has read and thrown away their use in the following). @@ -261,11 +259,9 @@ \tex_everyjob:D { \tex_the:D \tex_everyjob:D - \bool_if:nTF - { - \sys_if_engine_luatex_p: || - \sys_if_engine_xetex_p: - } + \bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } { \tex_font:D \exp_not:c { TU/lmr/m/n/10 } = "[lmroman10-regular.otf]/OT" \scan_stop: diff --git a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx index ef90edf32d5..658acbd3518 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx index e71d44c8ee9..02a22405d25 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % \maketitle % % \begin{documentation} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx index e6bc6fa3f8d..4d7ccd55a90 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx index 35c1b24b006..cd8a2822cec 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx index e639be1259a..463892caee7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx index 47a9536b72e..2cf6e06b8d5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx index 5c0e7151f5d..de04c7cf796 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx index cafc264b333..c51dd6069f7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -376,21 +376,39 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\fp_step_inline:nnnn} +% \begin{macro}{\fp_step_inline:nnnn, \fp_step_variable:nnnNn} +% \begin{macro}[aux]{\@@_step:NNnnnn} % As for \cs{int_step_inline:nnnn}, create a global function and apply it, % following up with a break point. % \begin{macrocode} -\cs_new_protected:Npn \fp_step_inline:nnnn #1#2#3#4 +\cs_new_protected:Npn \fp_step_inline:nnnn { \int_gincr:N \g__prg_map_int - \cs_gset_protected:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } - ##1 {#4} - \fp_step_function:nnnc {#1} {#2} {#3} + \exp_args:NNc \@@_step:NNnnnn + \cs_gset_protected:Npn { __prg_map_ \int_use:N \g__prg_map_int :w } + } +\cs_new_protected:Npn \fp_step_variable:nnnNn #1#2#3#4#5 + { + \int_gincr:N \g__prg_map_int + \exp_args:NNc \@@_step:NNnnnn + \cs_gset_protected:Npx + { __prg_map_ \int_use:N \g__prg_map_int :w } + {#1} {#2} {#3} + { + \tl_set:Nn \exp_not:N #4 {##1} + \exp_not:n {#5} + } + } +\cs_new_protected:Npn \@@_step:NNnnnn #1#2#3#4#5#6 + { + #1 #2 ##1 {#6} + \fp_step_function:nnnN {#3} {#4} {#5} #2 \__prg_break_point:Nn \scan_stop: { \int_gdecr:N \g__prg_map_int } } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macrocode} \__msg_kernel_new:nnn { kernel } { fp-bad-step } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx index 13d6b319723..83dca37310c 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -986,15 +986,23 @@ % the unknown word could be a mistyped function as well as a mistyped % constant, so there is no way to tell whether to look for arguments; % we do not. +% The standard requires \enquote{inf} and \enquote{infinity} and +% \enquote{nan} to be recognized regardless of case, but we probably +% don't want to allow every \pkg{l3fp} word to have an arbitrary +% mixture of lower and upper case, so we test and use a +% differently-named control sequence. % \begin{macrocode} \cs_new:Npn \@@_parse_word:Nw #1#2; { \cs_if_exist_use:cF { @@_parse_word_#2:N } { - \__msg_kernel_expandable_error:nnn - { kernel } { unknown-fp-word } {#2} - \exp_after:wN \c_nan_fp \exp:w \exp_end_continue_f:w - \@@_parse_infix:NN + \cs_if_exist_use:cF { @@_parse_caseless_ \str_fold_case:n {#2} :N } + { + \__msg_kernel_expandable_error:nnn + { kernel } { unknown-fp-word } {#2} + \exp_after:wN \c_nan_fp \exp:w \exp_end_continue_f:w + \@@_parse_infix:NN + } } #1 } @@ -1924,6 +1932,21 @@ % % \begin{macro}[aux, EXP] % { +% \@@_parse_caseless_inf:N, +% \@@_parse_caseless_infinity:N, +% \@@_parse_caseless_nan:N +% } +% Copies of \cs[no-index]{@@_parse_word_\ldots{}:N} commands, to allow +% arbitrary case as mandated by the standard. +% \begin{macrocode} +\cs_new_eq:NN \@@_parse_caseless_inf:N \@@_parse_word_inf:N +\cs_new_eq:NN \@@_parse_caseless_infinity:N \@@_parse_word_inf:N +\cs_new_eq:NN \@@_parse_caseless_nan:N \@@_parse_word_nan:N +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux, EXP] +% { % \@@_parse_word_pt:N , \@@_parse_word_in:N , % \@@_parse_word_pc:N , \@@_parse_word_cm:N , \@@_parse_word_mm:N , % \@@_parse_word_dd:N , \@@_parse_word_cc:N , \@@_parse_word_nd:N , diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx index edaf36026cf..d78c7c5e2de 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx index 88a50b7b6d4..dfc00ce2999 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx index 8cfde36c7fb..b11c8532a12 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % \maketitle % % \begin{documentation} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx index 88150107104..9ff46ddee9a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx @@ -38,7 +38,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx index 3c8aff7343a..380dd7f3641 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx @@ -47,7 +47,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -573,6 +573,20 @@ % \meta{code} should define a function of one argument~(|#1|). % \end{function} % +% \begin{function}[added = 2017-04-12]{\fp_step_variable:nnnNn} +% \begin{syntax} +% \cs{fp_step_variable:nnnNn} \\ +% ~~\Arg{initial value} \Arg{step} \Arg{final value} \meta{tl~var} \Arg{code} +% \end{syntax} +% This function first evaluates the \meta{initial value}, \meta{step} +% and \meta{final value}, all of which should be floating point expressions. +% Then for each \meta{value} from the \meta{initial value} to the +% \meta{final value} in turn (using \meta{step} between each +% \meta{value}), the \meta{code} is inserted into the input stream, +% with the \meta{tl~var} defined as the current \meta{value}. Thus +% the \meta{code} should make use of the \meta{tl~var}. +% \end{function} +% % \section{Some useful constants, and scratch variables} % % \begin{variable}[added = 2012-05-08]{\c_zero_fp, \c_minus_zero_fp} @@ -1029,8 +1043,8 @@ % Computes the sine, cosine, tangent, cotangent, cosecant, or secant % of the \meta{fpexpr} given in radians. For arguments given in % degrees, see \texttt{sind}, \texttt{cosd}, \emph{etc.} Note that -% since $\pi$~is irrational, $\operatorname{sin}(8pi)$ is not quite -% zero, while its analog $\operatorname{sind}(8\times 180)$ is exactly +% since $\pi$~is irrational, $\operatorname{sin}(8\mathrm{pi})$ is not quite +% zero, while its analogue $\operatorname{sind}(8\times 180)$ is exactly % zero. The trigonometric functions are undefined for % an argument of $\pm\infty$, leading to the \enquote{invalid % operation} exception. Additionally, evaluating tangent, @@ -1052,8 +1066,8 @@ % Computes the sine, cosine, tangent, cotangent, cosecant, or secant % of the \meta{fpexpr} given in degrees. For arguments given in % radians, see \texttt{sin}, \texttt{cos}, \emph{etc.} Note that -% since $\pi$~is irrational, $\operatorname{sin}(8pi)$ is not quite -% zero, while its analog $\operatorname{sind}(8\times 180)$ is exactly +% since $\pi$~is irrational, $\operatorname{sin}(8\mathrm{pi})$ is not quite +% zero, while its analogue $\operatorname{sind}(8\times 180)$ is exactly % zero. The trigonometric functions are undefined for % an argument of $\pm\infty$, leading to the \enquote{invalid % operation} exception. Additionally, evaluating tangent, diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx index 6514b100b29..7ea2be4fed0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -1322,7 +1322,7 @@ % code seen with token list variables. % \begin{macrocode} \cs_new_protected:Npn \int_set:Nn #1#2 - { #1 ~ \@@_eval:w #2\@@_eval_end: } + { #1 ~ \@@_eval:w #2 \@@_eval_end: } \cs_new_protected:Npn \int_gset:Nn { \tex_global:D \int_set:Nn } \cs_generate_variant:Nn \int_set:Nn { c } \cs_generate_variant:Nn \int_gset:Nn { c } @@ -1757,14 +1757,14 @@ { \int_gincr:N \g__prg_map_int \exp_args:NNc \@@_step:NNnnnn - \cs_gset:Npn + \cs_gset_protected:Npn { __prg_map_ \int_use:N \g__prg_map_int :w } } \cs_new_protected:Npn \int_step_variable:nnnNn #1#2#3#4#5 { \int_gincr:N \g__prg_map_int \exp_args:NNc \@@_step:NNnnnn - \cs_gset:Npx + \cs_gset_protected:Npx { __prg_map_ \int_use:N \g__prg_map_int :w } {#1}{#2}{#3} { diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx index 68edc695ad3..13c088c2785 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx index 21d8175361c..9fd49d2acd4 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx index 7427a556d09..466da628f8a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx index ad97bd167ae..d46b5c9fbf6 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx b/Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx index 7ba7671cfc4..b52cec077c2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3oldmodules.dtx @@ -42,7 +42,7 @@ % } % % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -149,5 +149,4 @@ % \end{macrocode} % % \end{implementation} -% -% \endinput + diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx index 2636aa962af..055fab38e6b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx index fc18d78ff68..b30ad2e1278 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -1065,13 +1065,15 @@ % of the form \cs{@@_pair:wn} \meta{key} \cs{s_@@} \Arg{value}, there % are a leading and a trailing tokens, but both are equal to % \cs{scan_stop:}, hence have no effect in such inline mapping. +% Such \cs{scan_stop:} could have affected ligatures if they appeared +% during the mapping. % \begin{macrocode} \cs_new_protected:Npn \prop_map_inline:Nn #1#2 { \cs_gset_eq:cN { __prg_map_ \int_use:N \g__prg_map_int :wn } \@@_pair:wn \int_gincr:N \g__prg_map_int - \cs_gset:Npn \@@_pair:wn ##1 \s_@@ ##2 {#2} + \cs_gset_protected:Npn \@@_pair:wn ##1 \s_@@ ##2 {#2} #1 \__prg_break_point:Nn \prop_map_break: { diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx index 7895de31175..6cfbf18f043 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -641,5 +641,3 @@ % \end{implementation} % % \PrintIndex -% -% \endinput diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx index e71c5c6de33..3681b4b4104 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx index 3db7d8feca1..0fc90333ab8 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx @@ -42,7 +42,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx index a7055a98d9a..9a7e9709631 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx index 6eb0a994ef1..90c2f79fc8b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -418,7 +418,7 @@ % % \section{String manipulation} % -% \begin{function}[rEXP, added = 2015-03-01] +% \begin{function}[EXP, added = 2015-03-01] % { % \str_lower_case:n, \str_lower_case:f, % \str_upper_case:n, \str_upper_case:f diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx index cb65137fb1a..ba1d67bd495 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -218,11 +218,9 @@ } \cs_if_exist:NT \ptex_kanjiskip:D { - \bool_if:nTF - { - \cs_if_exist_p:N \uptex_disablecjktoken:D && - \int_compare_p:nNn { \ptex_jis:D "2121 } = { "3000 } - } + \bool_lazy_and:nnTF + { \cs_if_exist_p:N \uptex_disablecjktoken:D } + { \int_compare_p:nNn { \ptex_jis:D "2121 } = { "3000 } } { \cs_gset_eq:NN \sys_if_engine_uptex:T \use:n \cs_gset_eq:NN \sys_if_engine_uptex:F \use_none:n diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index 6209a7b5f8d..d111582686f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -2211,7 +2211,8 @@ \cs_new_protected:Npn \tl_map_inline:nn #1#2 { \int_gincr:N \g__prg_map_int - \cs_gset:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} + \cs_gset_protected:cpn + { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} \exp_args:Nc \@@_map_function:Nn { __prg_map_ \int_use:N \g__prg_map_int :w } #1 \q_recursion_tail diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx index bda063e728c..9b74a8f8346 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % diff --git a/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx b/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx index 1041469c9bb..18465e22d54 100644 --- a/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx +++ b/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx @@ -23,8 +23,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/04/01] -%<package>\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} %<package> {} %<package> {% %<package> \PackageError{l3keys2e}{Support package l3kernel too old} @@ -60,7 +60,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -131,7 +131,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{l3keys2e}{2017/04/01}{} +\ProvidesExplPackage{l3keys2e}{2017/05/13}{} {LaTeX2e option processing using LaTeX3 keys} % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3packages/xfp/xfp.dtx b/Master/texmf-dist/source/latex/l3packages/xfp/xfp.dtx index 481b56eec02..0196c9cd775 100644 --- a/Master/texmf-dist/source/latex/l3packages/xfp/xfp.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xfp/xfp.dtx @@ -23,8 +23,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/04/01] -%<package>\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} %<package> {} %<package> {% %<package> \PackageError{xfpu}{Support package l3kernel too old} @@ -62,7 +62,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -143,7 +143,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xfp}{2017/04/01}{} +\ProvidesExplPackage{xfp}{2017/05/13}{} {L3 Floating point unit} % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx b/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx index 06c10494676..2556fa267bf 100644 --- a/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx @@ -24,8 +24,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/04/01] -%<package>\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} %<package> {} %<package> {% %<package> \PackageError{xfrac}{Support package l3kernel too old} @@ -63,7 +63,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -533,7 +533,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xfrac}{2017/04/01}{} +\ProvidesExplPackage{xfrac}{2017/05/13}{} {L3 Experimental split-level fractions} % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx index 46243389c01..95e08f91fdb 100644 --- a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx @@ -27,8 +27,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/04/01] -%<package>\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} %<package> {} %<package> {% %<package> \PackageError{xparse}{Support package l3kernel too old} @@ -67,7 +67,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -179,12 +179,12 @@ % |-NoValue-| if not present. % \item[G] As for \texttt{g} but returns \meta{default} if no value % is given: \texttt{G}\marg{default}. -% \item[e] An optional set of \emph{embellishments}, each of which requires a -% \emph{value}. If a key is not present, |-NoValue-| is returned. -% The returned data is a token list comprising one braced entry per key, -% ordered as for the key list in the argument specification. Given as -% \texttt{e}\marg{tokens}. All \meta{tokens} must be distinct. -% \emph{This is an experimental type}. +% \item[e] A set of optional \emph{embellishments}, each of which +% requires a \emph{value}: \texttt{e}\marg{tokens}. If an +% embellishment is not present, |-NoValue-| is returned. Each +% embellishment gives one argument, ordered as for the list of +% \meta{tokens} in the argument specification. All \meta{tokens} +% must be distinct. \emph{This is an experimental type}. % \item[E] As for \texttt{e} but returns one or more \meta{defaults} % if values are not given: \texttt{E}\marg{tokens}\marg{defaults}. See % Section~\ref{sec:embellishment} for more details. @@ -776,7 +776,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xparse}{2017/04/01}{} +\ProvidesExplPackage{xparse}{2017/05/13}{} {L3 Experimental document command parser} % \end{macrocode} % @@ -828,9 +828,10 @@ % \end{variable} % % \begin{variable}{\l_@@_current_arg_int} -% The number of the current argument being set up: this is used for creating -% the expandable auxiliary functions, and also to indicate if all arguments -% are \texttt{m}-type. +% The number of the current argument being set up: this is used to +% make sure there are at most 9 arguments, then for creating the +% expandable auxiliary functions and knowing how many arguments the +% code function should take. % \begin{macrocode} \int_new:N \l_@@_current_arg_int % \end{macrocode} @@ -1292,7 +1293,7 @@ % \end{macro} % % \begin{macro}{\@@_defaults:} -% \begin{macro}[aux]{\@@_defaults_def:, \@@_defaults_def:nn, \@@_defaults_def:nnn, \@@_defaults_def_aux:nn} +% \begin{macro}[aux]{\@@_defaults_def:, \@@_defaults_def:nn, \@@_defaults_def:nnn} % \begin{macro}[aux]{\@@_defaults_aux:, \@@_defaults_error:w} % First construct \cs{@@_tmp:w} (see below) that will receive % the arguments found so far and determine default values for any @@ -1332,13 +1333,7 @@ % |{#|\meta{arg number}|}| for arguments found in the input (whose % default will not be used) and otherwise % |{|\cs{exp_not:n}\Arg{default}|}| for arguments whose default will -% be used. The case of \texttt{E}-type arguments, detected by -% \cs{tl_if_head_is_group:nTF}, is special because we may need to -% partly use an argument found in the input and partly some default. -% This case is delayed until \cs{@@_tmp:w} is called: then we -% map through the original argument and its corresponding list of -% defaults; for each item (corresponding to one embellishment) if a -% value has already been found use it otherwise use the default. +% be used. % \begin{macrocode} \cs_new_protected:Npn \@@_defaults_def: { @@ -1357,36 +1352,18 @@ } \cs_new_protected:Npn \@@_defaults_def:nnn #1#2#3 { - \tl_if_head_is_group:nTF {#3} + \tl_put_right:Nx \l_@@_tmpa_tl { - \tl_put_right:Nn \l_@@_tmpa_tl - { + { + \exp_not:N \exp_not:n { - \exp_args:Nf \@@_tl_mapthread_function:nnN - { \tl_item:Nn \l_@@_args_tl {#1} } - {#3} - \@@_defaults_def_aux:nn + \@@_if_no_value:nTF {#2} + { \exp_not:o {#3} } + { \exp_not:n { ## #1 } } } - } - } - { - \@@_if_no_value:nTF {#2} - { - \tl_put_right:Nx \l_@@_tmpa_tl - { { \exp_not:N \exp_not:n { \exp_not:o {#3} } } } - } - { - \tl_put_right:Nn \l_@@_tmpa_tl - { { \exp_not:n { ## #1 } } } - } + } } } -\cs_new:Npn \@@_defaults_def_aux:nn #1#2 - { - \@@_if_no_value:nTF {#1} - { { \exp_not:n {#2} } } - { { \exp_not:n {#1} } } - } % \end{macrocode} % \end{macro} % \end{macro} @@ -1442,7 +1419,6 @@ % \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nnnNNn} % \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nnw} % \begin{macro}[EXP,aux]{\@@_end_expandable_defaults:nw} -% \begin{macro}[EXP,aux]{\@@_end_expandable_defaults_E:nnw} % Followed by a function |#1| to determine default values (or |?| if % there are no defaults), the code % |#2|, arguments that have been grabbed, then \cs{q_@@} and two generic @@ -1485,28 +1461,9 @@ } \cs_new:Npn \@@_end_expandable_defaults:nnw #1#2 { - \tl_if_head_is_group:nTF {#1} - { - \@@_end_expandable_defaults_E:nnw { } - #1 \q_nil \q_mark - #2 \q_nil - } - { - \@@_if_no_value:nTF {#2} - { \exp_args:No \@@_end_expandable_defaults:nw {#1} } - { \@@_end_expandable_defaults:nw {#2} } - } - } -\cs_new:Npn \@@_end_expandable_defaults_E:nnw #1#2#3 \q_mark #4 - { - \quark_if_nil:nTF {#2} - { \@@_end_expandable_defaults:nw {#1} } - { - \@@_if_no_value:nTF {#4} - { \@@_end_expandable_defaults_E:nnw { #1 {#2} } } - { \@@_end_expandable_defaults_E:nnw { #1 {#4} } } - #3 \q_mark - } + \@@_if_no_value:nTF {#2} + { \exp_args:No \@@_end_expandable_defaults:nw {#1} } + { \@@_end_expandable_defaults:nw {#2} } } \cs_new:Npn \@@_end_expandable_defaults:nw #1#2 \@@_end_expandable_defaults:nnnNNn #3 @@ -1518,7 +1475,6 @@ % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % \subsection{Normalizing the argument specifications} % @@ -1715,7 +1671,9 @@ % forbidden types for expandable commands. For \texttt{E}-type % require that there is at least one embellishment, that each one is a % single token, and that there aren't more optional arguments than -% embellishments. Then store the data in \cs{l_@@_arg_spec_tl}, and +% embellishments; also remember that each embellishment counts as one +% argument for \cs{l_@@_current_arg_int}. Then in each case +% store the data in \cs{l_@@_arg_spec_tl}, and % for later checks store in \cs{l_@@_last_delimiters_tl} the tokens % whose presence determines whether there is an optional argument (for % braces store |{}|, seen later as an empty delimiter). @@ -1741,6 +1699,7 @@ \@@_add_arg_spec:n { E {#1} {#2} } \tl_put_right:Nn \l_@@_last_delimiters_tl {#1} \bool_set_false:N \l_@@_grab_expandably_bool + \int_add:Nn \l_@@_current_arg_int { \tl_count:n {#1} - 1 } \@@_normalize_arg_spec_loop:n } \cs_new_protected:Npn \@@_normalize_E_unique_check:w #1#2 \q_stop @@ -1993,7 +1952,6 @@ \cs_new_protected:Npn \@@_prepare_signature_bypass:N #1 { \quark_if_recursion_tail_stop:N #1 - \int_incr:N \l_@@_current_arg_int \use:c { @@_add @@ -2015,11 +1973,12 @@ % type. All of the functions then call the loop function % \cs{@@_prepare_signature:N}. Default values of arguments are % collected by \cs{@@_add_default:n} rather than being stored with the -% argument. +% argument; this function and \cs{@@_add_default:} are also responsible +% for keeping track of \cs{l_@@_current_arg_int}. % % \begin{macro}{\@@_add_type_+:w} -% Making the next argument long means setting the flag and knocking one back -% off the total argument count. The \texttt{m} arguments are recorded here as +% Making the next argument long means setting the flag. The \texttt{m} +% arguments are recorded here as % this has to be done for every case where there is then a long argument. % \begin{macrocode} \cs_new_protected:cpn { @@_add_type_+:w } @@ -2027,7 +1986,6 @@ \@@_flush_m_args: \bool_set_true:N \l_@@_long_bool \bool_set_true:N \l_@@_prefixed_bool - \int_decr:N \l_@@_current_arg_int \@@_prepare_signature_bypass:N } % \end{macrocode} @@ -2044,7 +2002,6 @@ \@@_flush_m_args: \bool_set_true:N \l_@@_prefixed_bool \bool_set_true:N \l_@@_process_some_bool - \int_decr:N \l_@@_current_arg_int \tl_put_left:Nn \l_@@_process_one_tl { {#1} } \@@_prepare_signature_bypass:N } @@ -2214,7 +2171,7 @@ % the signature is done here. For mandatory arguments, the only question % is whether to add a long grabber. For optional arguments, there is % also a check to see if any mandatory arguments are still to be added. -% This is used to determine whether to skip spaces or not where +% This is used to determine whether to skip spaces or not when % searching for the argument. % \begin{macrocode} \cs_new_protected:Npn \@@_add_grabber_mandatory:N #1 @@ -2253,45 +2210,39 @@ % \end{macro} % % \begin{macro}{\@@_add_default:n, \@@_add_default:, \@@_add_default_E:nn} -% \begin{macro}[aux]{\@@_add_default_E_aux:n} % Store the default value of an argument, or rather code that gives % that default value (it may involve other arguments). This is % \cs{c_@@_no_value_tl} for arguments with no actual default or with -% default |-NoValue-|; \cs{prg_do_nothing:} followed by a default -% value for most others, and a token list of braced arguments for -% \texttt{E}-type arguments. For \texttt{E}-type arguments, pad the -% defaults |#2| with some |{-NoValue-}| until there are as many as -% embellishments~|#1|. These functions are also used when defining -% expandable commands. +% default |-NoValue-|; and (in a brace group) \cs{prg_do_nothing:} +% followed by a default value for others. For \texttt{E}-type +% arguments, pad the defaults |#2| with some \cs{c_@@_no_value_tl} +% until there are as many as embellishments~|#1|. These functions are +% also used when defining expandable commands. % \begin{macrocode} \cs_new_protected:Npn \@@_add_default:n #1 { \@@_if_no_value:nTF {#1} { \@@_add_default: } { + \int_incr:N \l_@@_current_arg_int \bool_set_true:N \l_@@_defaults_bool \tl_put_right:Nn \l_@@_defaults_tl { { \prg_do_nothing: #1 } } } } \cs_new_protected:Npn \@@_add_default: - { \tl_put_right:Nn \l_@@_defaults_tl { \c_@@_no_value_tl } } + { + \int_incr:N \l_@@_current_arg_int + \tl_put_right:Nn \l_@@_defaults_tl { \c_@@_no_value_tl } + } \cs_new_protected:Npn \@@_add_default_E:nn #1#2 { - \bool_set_true:N \l_@@_defaults_bool - \tl_put_right:Nx \l_@@_defaults_tl - { - { - \tl_map_function:nN {#2} \@@_add_default_E_aux:n - \prg_replicate:nn - { \tl_count:n {#1} - \tl_count:n {#2} } - { { \c_@@_no_value_tl } } - } - } + \tl_map_function:nN {#2} \@@_add_default:n + \prg_replicate:nn + { \tl_count:n {#1} - \tl_count:n {#2} } + { \@@_add_default: } } -\cs_new:Npn \@@_add_default_E_aux:n #1 { \exp_not:n { {#1} } } % \end{macrocode} % \end{macro} -% \end{macro} % % \subsection{Setting up expandable types} % @@ -2310,7 +2261,6 @@ \cs_new_protected:cpn { @@_add_expandable_type_+:w } { \bool_set_true:N \l_@@_long_bool - \int_decr:N \l_@@_current_arg_int \@@_prepare_signature:N } % \end{macrocode} @@ -2377,7 +2327,7 @@ % the auxiliary and the token in \cs{l_@@_tmpb_tl}, before appending % the whole set of these pairs to the signature, and an equal number % of |-NoValue-| markers (regardless of the default values of -% arguments). +% arguments). Set the current argument appropriately. % \begin{macrocode} \cs_new_protected:Npn \@@_add_expandable_type_E:w #1#2 { @@ -2766,18 +2716,14 @@ \tl_set:Nn \l_@@_signature_tl {#2} \cs_set_protected:Npn \@@_grab_E_finalise: { - \tl_clear:N \l_@@_tmpa_tl \tl_map_inline:nn {#1} { \prop_get:NnNF \l_@@_tmp_prop {####1} \l_@@_tmpb_tl { \tl_set_eq:NN \l_@@_tmpb_tl \c_@@_no_value_tl } - \tl_set:Nx \l_@@_tmpa_tl - { - \exp_not:V \l_@@_tmpa_tl - { \exp_not:V \l_@@_tmpb_tl } - } + \tl_put_right:Nx \l_@@_args_tl + { { \exp_not:V \l_@@_tmpb_tl } } } - \@@_add_arg:V \l_@@_tmpa_tl + \l_@@_signature_tl \@@_run_code: } \@@_grab_E_loop:nnN {#4} { } #1 \q_recursion_tail \q_recursion_stop } @@ -3570,7 +3516,7 @@ \cs_new:Npn \@@_expandable_grab_E_find:nnw #1#2#3 \q_nil #4 \q_@@ #5#6#7#8 { \@@_expandable_grab_E_aux:w {#1} { #2 {#8} #3 } #4 \q_@@ #5 #6 #7 } \cs_new:Npn \@@_expandable_grab_E_end:nnw #1#2#3 \q_@@ #4#5#6 - { #3 {#2} \q_@@ #4 #5 {#1} } + { #3 #2 \q_@@ #4 #5 {#1} } % \end{macrocode} % \end{macro} % \end{macro} diff --git a/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx b/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx index d210104e72e..069612e4d0d 100644 --- a/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx @@ -27,8 +27,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2017/04/01] -%<package>\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +%<package>\@ifpackagelater{expl3}{2017/05/13} %<package> {} %<package> {% %<package> \PackageError{xtemplate}{Support package l3kernel too old} @@ -63,7 +63,7 @@ % }^^A % } % -% \date{Released 2017/04/01} +% \date{Released 2017/05/13} % % \maketitle % @@ -682,7 +682,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xtemplate}{2017/04/01}{} +\ProvidesExplPackage{xtemplate}{2017/05/13}{} {L3 Experimental prototype document functions} % \end{macrocode} % diff --git a/Master/texmf-dist/tex/latex/l3build/l3build.lua b/Master/texmf-dist/tex/latex/l3build/l3build.lua index b3d55b0fb00..f514429cf7d 100644 --- a/Master/texmf-dist/tex/latex/l3build/l3build.lua +++ b/Master/texmf-dist/tex/latex/l3build/l3build.lua @@ -22,8 +22,8 @@ for those people who are interested. --]] --- Version information: should be identical to that in l3build.dtx -release_date = "2017/04/01" +-- Version information +release_date = "2017/05/13" -- "module" is a deprecated function in Lua 5.2: as we want the name -- for other purposes, and it should eventually be 'free', simply @@ -38,7 +38,7 @@ bundle = bundle or "" -- Sanity check if module == "" and bundle == "" then - if string.match(arg[0], ".*l3build%.lua$") then + if string.match(arg[0], "l3build%.lua$") then print( "\n" .. "Error: Call l3build using a configuration file, not directly.\n" @@ -57,7 +57,7 @@ end maindir = maindir or "." -- Substructure for tests and support files -testfiledir = testfiledir or "testfiles" -- Set to "" to cancel any tests +testfiledir = testfiledir or "testfiles" testsuppdir = testsuppdir or testfiledir .. "/support" supportdir = supportdir or maindir .. "/support" @@ -113,7 +113,7 @@ unpackdeps = unpackdeps or { } -- Executable names plus following options typesetexe = typesetexe or "pdflatex" unpackexe = unpackexe or "tex" -zipexe = "zip" +zipexe = zipexe or "zip" checkopts = checkopts or "-interaction=nonstopmode" cmdchkopts = cmdchkopts or "-interaction=batchmode" @@ -128,7 +128,6 @@ stdengine = stdengine or "pdftex" -- Enable access to trees outside of the repo -- As these may be set false, a more elaborate test than normal is needed --- here if checksearch == nil then checksearch = true end @@ -156,8 +155,8 @@ asciiengines = asciiengines or {"pdftex"} checkruns = checkruns or 1 epoch = epoch or 1463734800 maxprintline = maxprintline or 79 -packtdszip = packtdszip or false -- Not actually needed but clearer -scriptname = scriptname or "build.lua" -- Script used in each directory +packtdszip = packtdszip or false +scriptname = scriptname or "build.lua" typesetcmds = typesetcmds or "" versionform = versionform or "" @@ -171,11 +170,50 @@ pdfext = pdfext or ".pdf" psext = psext or ".ps" tlgext = tlgext or ".tlg" --- Run time options --- These are parsed into a global table, and all optional args --- are made available as a related global var - -function argparse() +-- File operations are aided by the LuaFileSystem module +local lfs = require("lfs") + +-- Local access to functions +local assert = assert +local ipairs = ipairs +local next = next +local print = print +local select = select +local tonumber = tonumber +local close = io.close +local lines = io.lines +local open = io.open +local output = io.output +local stderr = io.stderr +local write = io.write +local set_program_name = kpse.set_program_name +local var_value = kpse.var_value +local lfs_attributes = lfs.attributes +local lfs_dir = lfs.dir +local os_date = os.date +local execute = os.execute +local exit = os.exit +local getenv = os.getenv +local os_remove = os.remove +local os_type = os.type +local luatex_revision = status.luatex_revision +local luatex_version = status.luatex_version +local char = string.char +local find = string.find +local format = string.format +local gmatch = string.gmatch +local gsub = string.gsub +local len = string.len +local match = string.match +local sub = string.sub +local concat = table.concat +local insert = table.insert +local utf8_char = unicode.utf8.char + +-- Parse command line options +-- This is done as a function (rather than do ... end) as it allows early +-- termination (break) +local function argparse() local result = { } local files = { } local long_options = @@ -212,6 +250,7 @@ function argparse() release = true, testfiledir = true } + local args = args -- arg[1] is a special case: must be a command or "-h"/"--help" -- Deal with this by assuming help and storing only apparently-valid -- input @@ -219,7 +258,7 @@ function argparse() result["target"] = "help" if a then -- No options are allowed in position 1, so filter those out - if not string.match(a, "^%-") then + if not match(a, "^%-") then result["target"] = a end end @@ -231,7 +270,7 @@ function argparse() local function remainder(num) local files = { } for i = num, #arg do - table.insert(files, arg[i]) + insert(files, arg[i]) end return files end @@ -247,25 +286,26 @@ function argparse() break end -- Look for optionals - local opt, optarg + local opt + local optarg local opts -- Look for and option and get it into a variable - if string.match(a, "^%-") then - if string.match(a, "^%-%-") then + if match(a, "^%-") then + if match(a, "^%-%-") then opts = long_options - local pos = string.find(a, "=", 1, true) + local pos = find(a, "=", 1, true) if pos then - opt = string.sub(a, 3, pos - 1) - optarg = string.sub(a, pos + 1) + opt = sub(a, 3, pos - 1) + optarg = sub(a, pos + 1) else - opt = string.sub(a,3) + opt = sub(a, 3) end else opts = short_options - opt = string.sub(a, 2, 2) + opt = sub(a, 2, 2) -- Only set optarg if it is there if #a > 2 then - optarg = string.sub(a, 3) + optarg = sub(a, 3) end end -- Now check that the option is valid and sort out the argument @@ -277,25 +317,24 @@ function argparse() if reqarg and not optarg then optarg = arg[i + 1] if not optarg then - io.stderr:write("Missing value for option " .. a .."\n") + stderr:write("Missing value for option " .. a .."\n") return {"help"} end i = i + 1 end if not reqarg and optarg then - io.stderr:write("Value not allowed for option " .. a .."\n") + stderr:write("Value not allowed for option " .. a .."\n") return {"help"} end else - io.stderr:write("Unknown option " .. a .."\n") + stderr:write("Unknown option " .. a .."\n") return {"help"} end -- Store the result if optarg then local opts = result[optname] or { } - local match - for match in string.gmatch(optarg, "([^,%s]+)") do - table.insert(opts, match) + for hit in gmatch(optarg, "([^,%s]+)") do + insert(opts, hit) end result[optname] = opts else @@ -312,15 +351,14 @@ function argparse() return result end -userargs = argparse() +options = argparse() -optdate = userargs["date"] -optengines = userargs["engine"] -opthalt = userargs["halt"] -opthelp = userargs["help"] -optpdf = userargs["pdf"] -optquiet = userargs["quiet"] -optrelease = userargs["release"] +local optdate = options["date"] +local optengines = options["engine"] +local opthalt = options["halt"] +local optpdf = options["pdf"] +local optquiet = options["quiet"] +local optrelease = options["release"] -- Convert a file glob into a pattern for use by e.g. string.gub -- Based on https://github.com/davidm/lua-glob-pattern @@ -353,7 +391,7 @@ optrelease = userargs["release"] (end license) --]] -function glob_to_pattern(glob) +local function glob_to_pattern(glob) local pattern = "^" -- pattern being built local i = 0 -- index in glob @@ -361,13 +399,13 @@ function glob_to_pattern(glob) -- escape pattern char local function escape(char) - return string.match(char, "^%w$") and char or "%" .. char + return match(char, "^%w$") and char or "%" .. char end -- Convert tokens. while true do i = i + 1 - char = string.sub(glob, i, i) + char = sub(glob, i, i) if char == "" then pattern = pattern .. "$" break @@ -380,7 +418,7 @@ function glob_to_pattern(glob) print("[...] syntax not supported in globs!") elseif char == "\\" then i = i + 1 - char = string.sub(glob, i, i) + char = sub(glob, i, i) if char == "" then pattern = pattern .. "\\$" break @@ -393,52 +431,41 @@ function glob_to_pattern(glob) return pattern end --- File operation support --- Much of this is OS-dependent as Lua offers a very limited range of file --- operations 'natively'. - -- Detect the operating system in use -- Support items are defined here for cases where a single string can cover -- both Windows and Unix cases: more complex situations are handled inside -- the support functions -if os.type == "windows" then - os_ascii = "@echo." - os_cmpexe = os.getenv("cmpexe") or "fc /b" - os_cmpext = os.getenv("cmpext") or ".cmp" - os_concat = "&" - os_diffext = os.getenv("diffext") or ".fc" - os_diffexe = os.getenv("diffexe") or "fc /n" - os_grepexe = "findstr /r" - os_newline = "\n" - if tonumber(status.luatex_version) < 100 or - (tonumber(status.luatex_version) == 100 - and tonumber(status.luatex_revision) < 4) then +os_concat = ";" +os_null = "/dev/null" +os_pathsep = ":" +os_setenv = "export" +os_yes = "printf 'y\\n%.0s' {1..200}" +local os_ascii = "echo \"\"" +local os_cmpexe = getenv("cmpexe") or "cmp" +local os_cmpext = getenv("cmpext") or ".cmp" +local os_diffext = getenv("diffext") or ".diff" +local os_diffexe = getenv("diffexe") or "diff -c --strip-trailing-cr" +local os_grepexe = "grep" +local os_newline = "\n" +if os_type == "windows" then + os_ascii = "@echo." + os_cmpexe = getenv("cmpexe") or "fc /b" + os_cmpext = getenv("cmpext") or ".cmp" + os_concat = "&" + os_diffext = getenv("diffext") or ".fc" + os_diffexe = getenv("diffexe") or "fc /n" + os_grepexe = "findstr /r" + os_newline = "\n" + if tonumber(luatex_version) < 100 or + (tonumber(luatex_version) == 100 + and tonumber(luatex_revision) < 4) then os_newline = "\r\n" end - os_null = "nul" - os_pathsep = ";" - os_setenv = "set" - os_windows = true - os_yes = "for /l %I in (1,1,200) do @echo y" -else - os_ascii = "echo \"\"" - os_cmpexe = os.getenv("cmpexe") or "cmp" - os_cmpext = os.getenv("cmpext") or ".cmp" - os_concat = ";" - os_diffext = os.getenv("diffext") or ".diff" - os_diffexe = os.getenv("diffexe") or "diff -c --strip-trailing-cr" - os_grepexe = "grep" - os_newline = "\n" - os_null = "/dev/null" - os_pathsep = ":" - os_setenv = "export" - os_windows = false - os_yes = "printf 'y\\n%.0s' {1..200}" -end - --- File operations are aided by the LuaFileSystem module, which is available --- within texlua -lfs = require("lfs") + os_null = "nul" + os_pathsep = ";" + os_setenv = "set" + os_yes = "for /l %I in (1,1,200) do @echo y" +end -- For cleaning out a directory, which also ensures that it exists function cleandir(dir) @@ -454,20 +481,20 @@ function cp(glob, source, dest) local errorlevel for _,i in ipairs(filelist(source, glob)) do local source = source .. "/" .. i - if os_windows then - if lfs.attributes(source)["mode"] == "directory" then - errorlevel = os.execute( + if os_type == "windows" then + if lfs_attributes(source)["mode"] == "directory" then + errorlevel = execute( "xcopy /y /e /i " .. unix_to_win(source) .. " " .. unix_to_win(dest .. "/" .. i) .. " > nul" ) else - errorlevel = os.execute( + errorlevel = execute( "xcopy /y " .. unix_to_win(source) .. " " .. unix_to_win(dest) .. " > nul" ) end else - errorlevel = os.execute("cp -rf " .. source .. " " .. dest) + errorlevel = execute("cp -rf " .. source .. " " .. dest) end if errorlevel ~=0 then return errorlevel @@ -479,11 +506,11 @@ end -- OS-dependent test for a directory function direxists(dir) local errorlevel - if os_windows then + if os_type == "windows" then errorlevel = - os.execute("if not exist \"" .. unix_to_win(dir) .. "\" exit 1") + execute("if not exist \"" .. unix_to_win(dir) .. "\" exit 1") else - errorlevel = os.execute("[ -d " .. dir .. " ]") + errorlevel = execute("[ -d " .. dir .. " ]") end if errorlevel ~= 0 then return false @@ -492,9 +519,9 @@ function direxists(dir) end function fileexists(file) - local f = io.open(file, "r") + local f = open(file, "r") if f ~= nil then - io.close(f) + close(f) return true else return false @@ -503,7 +530,6 @@ end -- Generate a table containing all file names of the given glob or all files -- if absent --- Not actually OS-dependent but in the same area function filelist(path, glob) local files = { } local pattern @@ -511,14 +537,14 @@ function filelist(path, glob) pattern = glob_to_pattern(glob) end if direxists(path) then - for entry in lfs.dir(path) do + for entry in lfs_dir(path) do if pattern then - if string.match(entry, pattern) then - table.insert(files, entry) + if match(entry, pattern) then + insert(files, entry) end else if entry ~= "." and entry ~= ".." then - table.insert(files, entry) + insert(files, entry) end end end @@ -527,57 +553,43 @@ function filelist(path, glob) end function mkdir(dir) - if os_windows then + if os_type == "windows" then -- Windows (with the extensions) will automatically make directory trees -- but issues a warning if the dir already exists: avoid by including a test local dir = unix_to_win(dir) - return os.execute( + return execute( "if not exist " .. dir .. "\\nul " .. "mkdir " .. dir ) else - return os.execute("mkdir -p " .. dir) + return execute("mkdir -p " .. dir) end end --- Find the relationship between two directories -function relpath(target, source) - -- A shortcut for the case where the two are the same - if target == source then - return "" - end - local resultdir = "" - local trimpattern = "^[^/]*/" - -- Trim off identical leading directories - while - (string.match(target, trimpattern) or "X") == - (string.match(target, trimpattern) or "Y") do - target = string.gsub(target, trimpattern, "") - source = string.gsub(source, trimpattern, "") - end - -- Go up from the source - for i = 0, select(2, string.gsub(target, "/", "")) do - resultdir = resultdir .. "../" - end - -- Return the relative part plus the unique part of the target - return resultdir .. target +-- Return an absolute path from a relative one +function abspath(path) + local oldpwd = lfs.currentdir() + lfs.chdir(path) + local result = lfs.currentdir() + lfs.chdir(oldpwd) + return result end -- Rename function ren(dir, source, dest) local dir = dir .. "/" - if os_windows then - return os.execute("ren " .. unix_to_win(dir) .. source .. " " .. dest) + if os_type == "windows" then + return execute("ren " .. unix_to_win(dir) .. source .. " " .. dest) else - return os.execute("mv " .. dir .. source .. " " .. dir .. dest) + return execute("mv " .. dir .. source .. " " .. dir .. dest) end end -- Remove file(s) based on a glob function rm(source, glob) for _,i in ipairs(filelist(source, glob)) do - os.remove(source .. "/" .. i) + os_remove(source .. "/" .. i) end - -- os.remove doesn't give a sensible errorlevel + -- os_remove doesn't give a sensible errorlevel return 0 end @@ -585,21 +597,21 @@ end function rmdir(dir) -- First, make sure it exists to avoid any errors mkdir(dir) - if os_windows then - return os.execute("rmdir /s /q " .. unix_to_win(dir)) + if os_type == "windows" then + return execute("rmdir /s /q " .. unix_to_win(dir)) else - return os.execute("rm -r " .. dir) + return execute("rm -r " .. dir) end end -- Run a command in a given directory function run(dir, cmd) - return os.execute("cd " .. dir .. os_concat .. cmd) + return execute("cd " .. dir .. os_concat .. cmd) end -- Deal with the fact that Windows and Unix use different path separators function unix_to_win(path) - return string.gsub(path, "/", "\\") + return gsub(path, "/", "\\") end -- @@ -607,25 +619,25 @@ end -- -- Do some subtarget for all modules in a bundle -function allmodules(target) +local function allmodules(target) + local date = "" + if optdate then + date = " --date=" .. optdate[1] + end + local engines = "" + if optengines then + engines = " --engine=" .. concat(optengines, ",") + end + local release = "" + if optrelease then + release = " --release=" .. optrelease[1] + end for _,i in ipairs(modules) do print( "Running script " .. scriptname .. " with target \"" .. target .. "\" for module " .. i ) - local date = "" - if optdate then - date = " --date=" .. optdate[1] - end - local engines = "" - if optengines then - engines = " --engine=" .. table.concat(optengines, ",") - end - local release = "" - if optrelease then - release = " --release=" .. optrelease[1] - end local errorlevel = run( i, "texlua " .. scriptname .. " " .. target @@ -645,7 +657,7 @@ end -- Set up the check system files: needed for checking one or more tests and -- for saving the test files -function checkinit() +local function checkinit() cleandir(testdir) depinstall(checkdeps) -- Copy dependencies to the test directory itself: this makes the paths @@ -669,7 +681,7 @@ function checkinit() for _,i in ipairs(checksuppfiles) do cp(i, supportdir, testdir) end - os.execute(os_ascii .. ">" .. testdir .. "/ascii.tcx") + execute(os_ascii .. ">" .. testdir .. "/ascii.tcx") end -- Copy files to the main CTAN release directory @@ -709,18 +721,18 @@ function copytds() moduledir = module end end - local installdir = tdsdir .. "/" .. dest .. "/" .. moduledir -- Convert the file table(s) to a list of individual files local filenames = { } for _,i in ipairs(files) do for _,j in ipairs(i) do for _,k in ipairs(filelist(source, j)) do - table.insert(filenames, k) + insert(filenames, k) end end end -- The target is only created if there are actual files to install if next(filenames) ~= nil then + local installdir = tdsdir .. "/" .. dest .. "/" .. moduledir mkdir(installdir) for _,i in ipairs(filenames) do cp(i, source, installdir) @@ -753,21 +765,21 @@ end -- Convert the raw log file into one for comparison/storage: keeps only -- the 'business' part from the tests and removes system-dependent stuff -function formatlog(logfile, newfile, engine) +local function formatlog(logfile, newfile, engine) local maxprintline = maxprintline if engine == "luatex" or engine == "luajittex" then maxprintline = maxprintline + 1 -- Deal with an out-by-one error end local function killcheck(line) -- Skip lines containing file dates - if string.match(line, "[^<]%d%d%d%d/%d%d/%d%d") then + if match(line, "[^<]%d%d%d%d/%d%d/%d%d") then return true elseif -- Skip \openin/\openout lines in web2c 7.x -- As Lua doesn't allow "(in|out)", a slightly complex approach: -- do a substitution to check the line is exactly what is required! - string.match( - string.gsub(line, "^\\openin", "\\openout"), "^\\openout%d%d? = " + match( + gsub(line, "^\\openin", "\\openout"), "^\\openout%d%d? = " ) then return true end @@ -777,13 +789,13 @@ function formatlog(logfile, newfile, engine) local function normalize(line, lastline) -- Zap line numbers from \show, \showbox, \box_show and the like: -- do this before wrapping lines - line = string.gsub(line, "^l%.%d+ ", "l. ...") + line = gsub(line, "^l%.%d+ ", "l. ...") -- Also from lua stack traces. - line = string.gsub(line, "lua:%d+: in function", "lua:...: in function") + line = gsub(line, "lua:%d+: in function", "lua:...: in function") -- Allow for wrapped lines: preserve the content and wrap -- Skip lines that have an explicit marker for truncation - if string.len(line) == maxprintline and - not string.match(line, "%.%.%.$") then + if len(line) == maxprintline and + not match(line, "%.%.%.$") then return "", (lastline or "") .. line end local line = (lastline or "") .. line @@ -792,77 +804,76 @@ function formatlog(logfile, newfile, engine) -- This needs to extract the base name from the log name, -- and one to allow for the case that there might be "-" chars -- in the name (other cases are ignored) - line = string.gsub( + line = gsub( line, - string.gsub( - string.match("/" .. logfile, ".*/(.*)%" .. logext .. "$"), + gsub( + match("/" .. logfile, ".*/(.*)%" .. logext .. "$"), "-", "%%-" ), "" ) -- Zap ./ at begin of filename - line = string.gsub(line, "%(%.%/", "(") + line = gsub(line, "%(%.%/", "(") -- Zap paths if places other than 'here' are accessible if checksearch then local pattern = "%w?:?/[^ ]*/([^/%(%)]*%.%w*)" -- Files loaded from TeX: all start ( -- ) - line = string.gsub(line, "%(" .. pattern, "(../%1") + line = gsub(line, "%(" .. pattern, "(../%1") -- luaotfload files start with keywords - line = string.gsub(line, "from " .. pattern .. "%(", "from. ./%1(") - line = string.gsub(line, ": " .. pattern .. "%)", ": ../%1)") + line = gsub(line, "from " .. pattern .. "%(", "from. ./%1(") + line = gsub(line, ": " .. pattern .. "%)", ": ../%1)") end -- Deal with the fact that "(.aux)" may have still a leading space - line = string.gsub(line, "^ %(%.aux%)", "(.aux)") + line = gsub(line, "^ %(%.aux%)", "(.aux)") -- Merge all of .fd data into one line so will be removed later - if string.match(line, "^ *%([%.%/%w]+%.fd[^%)]*$") then + if match(line, "^ *%([%.%/%w]+%.fd[^%)]*$") then lastline = (lastline or "") .. line return "", (lastline or "") .. line end -- TeX90/XeTeX knows only the smaller set of dimension units - line = string.gsub( + line = gsub( line, "cm, mm, dd, cc, bp, or sp", "cm, mm, dd, cc, nd, nc, bp, or sp" ) -- Normalise a case where fixing a TeX bug changes the message text - line = string.gsub(line, "\\csname\\endcsname ", "\\csname\\endcsname") + line = gsub(line, "\\csname\\endcsname ", "\\csname\\endcsname") -- Zap "on line <num>" and replace with "on line ..." -- Two similar cases, Lua patterns mean we need to do them separately - line = string.gsub(line, "on line %d*", "on line ...") - line = string.gsub(line, "on input line %d*", "on input line ...") + line = gsub(line, "on line %d*", "on line ...") + line = gsub(line, "on input line %d*", "on input line ...") -- Tidy up to ^^ notation for i = 0, 31 do - line = string.gsub(line, string.char(i), "^^" .. string.char(64 + i)) + line = gsub(line, char(i), "^^" .. char(64 + i)) end -- Remove 'normal' direction information on boxes with (u)pTeX - line = string.gsub(line, ",? yoko direction,?", "") + line = gsub(line, ",? yoko direction,?", "") -- Remove the \special line that in DVI mode keeps PDFs comparable - if string.match(line, "^%.*\\special%{pdf: docinfo << /Creator") then + if match(line, "^%.*\\special%{pdf: docinfo << /Creator") then return "" end -- Remove the \special line possibly present in DVI mode for paper size - if string.match(line, "^%.*\\special%{papersize") then + if match(line, "^%.*\\special%{papersize") then return "" end -- Remove ConTeXt stuff - if string.match(line, "^backend >") or - string.match(line, "^close source >") or - string.match(line, "^mkiv lua stats >") or - string.match(line, "^pages >") or - string.match(line, "^system >") or - string.match(line, "^used file >") or - string.match(line, "^used option >") or - string.match(line, "^used structure >") then + if match(line, "^backend >") or + match(line, "^close source >") or + match(line, "^mkiv lua stats >") or + match(line, "^pages >") or + match(line, "^system >") or + match(line, "^used file >") or + match(line, "^used option >") or + match(line, "^used structure >") then return "" end -- A tidy-up to keep LuaTeX and other engines in sync - local utf8_char = unicode.utf8.char - line = string.gsub(line, utf8_char(127), "^^?") + line = gsub(line, utf8_char(127), "^^?") -- Unicode engines display chars in the upper half of the 8-bit range: -- tidy up to match pdfTeX if an ASCII engine is in use if next(asciiengines) then for i = 128, 255 do - line = string.gsub(line, utf8_char(i), "^^" .. string.format("%02x", i)) + line = gsub(line, utf8_char(i), "^^" .. format("%02x", i)) end end return line, lastline @@ -872,74 +883,74 @@ function formatlog(logfile, newfile, engine) local prestart = true local skipping = false -- Read the entire log file as a binary: deals with ^@/^[, etc. - local file = assert(io.open(logfile, "rb")) - local contents = string.gsub(file:read("*all") .. "\n", "\r\n", "\n") - io.close(file) - for line in string.gmatch(contents, "([^\n]*)\n") do + local file = assert(open(logfile, "rb")) + local contents = gsub(file:read("*all") .. "\n", "\r\n", "\n") + close(file) + for line in gmatch(contents, "([^\n]*)\n") do if line == "START-TEST-LOG" then prestart = false elseif line == "END-TEST-LOG" then break elseif line == "OMIT" then skipping = true - elseif string.match(line, "^%)?TIMO$") then + elseif match(line, "^%)?TIMO$") then skipping = false elseif not prestart and not skipping then line, lastline = normalize(line, lastline) - if not string.match(line, "^ *$") and not killcheck(line) then + if not match(line, "^ *$") and not killcheck(line) then newlog = newlog .. line .. os_newline end end end - local newfile = io.open(newfile, "w") - io.output(newfile) - io.write(newlog) - io.close(newfile) + local newfile = open(newfile, "w") + output(newfile) + write(newlog) + close(newfile) end -- Additional normalization for LuaTeX -function formatlualog(logfile, newfile) +local function formatlualog(logfile, newfile) local function normalize(line, lastline, dropping) -- Find \discretionary or \whatsit lines: -- These may come back later - if string.match(line, "^%.+\\discretionary$") or - string.match(line, "^%.+\\discretionary %(penalty 50%)$") or - string.match(line, "^%.+\\discretionary50%|$") or - string.match(line, "^%.+\\discretionary50%| replacing $") or - string.match(line, "^%.+\\whatsit$") then + if match(line, "^%.+\\discretionary$") or + match(line, "^%.+\\discretionary %(penalty 50%)$") or + match(line, "^%.+\\discretionary50%|$") or + match(line, "^%.+\\discretionary50%| replacing $") or + match(line, "^%.+\\whatsit$") then return "", line end -- For \mathon, we always need this line but the next -- may be affected - if string.match(line, "^%.+\\mathon$") then + if match(line, "^%.+\\mathon$") then return line, line end -- LuaTeX has a flexible output box - line = string.gsub(line,"\\box\\outputbox", "\\box255") + line = gsub(line,"\\box\\outputbox", "\\box255") -- LuaTeX identifies spaceskip glue - line = string.gsub(line,"%(\\spaceskip%) ", " ") + line = gsub(line,"%(\\spaceskip%) ", " ") -- Remove 'display' at end of display math boxes: -- LuaTeX omits this as it includes direction in all cases - line = string.gsub(line, "(\\hbox%(.*), display$", "%1") + line = gsub(line, "(\\hbox%(.*), display$", "%1") -- Remove 'normal' direction information on boxes: -- any bidi/vertical stuff will still show - line = string.gsub(line, ", direction TLT", "") + line = gsub(line, ", direction TLT", "") -- Find glue setting and round out the last place local function round_digits(l, m) - return string.gsub( + return gsub( l, m .. " (%-?)%d+%.%d+", m .. " %1" - .. string.format( + .. format( "%.3f", - string.match(line, m .. " %-?(%d+%.%d+)") or 0 + match(line, m .. " %-?(%d+%.%d+)") or 0 ) ) end - if string.match(line, "glue set %-?%d+%.%d+") then + if match(line, "glue set %-?%d+%.%d+") then line = round_digits(line, "glue set") end - if string.match( + if match( line, "glue %-?%d+%.%d+ plus %-?%d+%.%d+ minus %-?%d+%.%d+$" ) then @@ -948,35 +959,35 @@ function formatlualog(logfile, newfile) line = round_digits(line, "minus") end -- LuaTeX writes ^^M as a new line, which we lose - line = string.gsub(line, "%^%^M", "") + line = gsub(line, "%^%^M", "") -- Remove U+ notation in the "Missing character" message - line = string.gsub( + line = gsub( line, "Missing character: There is no (%^%^..) %(U%+(....)%)", "Missing character: There is no %1" ) -- A function to handle the box prefix part local function boxprefix(s) - return string.gsub(string.match(s, "^(%.+)"), "%.", "%%.") + return gsub(match(s, "^(%.+)"), "%.", "%%.") end -- 'Recover' some discretionary data - if string.match(lastline, "^%.+\\discretionary %(penalty 50%)$") and - string.match(line, boxprefix(lastline) .. "%.= ") then - return string.gsub(line, "%.= ", ""),"" + if match(lastline, "^%.+\\discretionary %(penalty 50%)$") and + match(line, boxprefix(lastline) .. "%.= ") then + return gsub(line, "%.= ", ""),"" end -- Where the last line was a discretionary, looks for the -- info one level in about what it represents - if string.match(lastline, "^%.+\\discretionary$") or - string.match(lastline, "^%.+\\discretionary %(penalty 50%)$") or - string.match(lastline, "^%.+\\discretionary50%|$") or - string.match(lastline, "^%.+\\discretionary50%| replacing $") then + if match(lastline, "^%.+\\discretionary$") or + match(lastline, "^%.+\\discretionary %(penalty 50%)$") or + match(lastline, "^%.+\\discretionary50%|$") or + match(lastline, "^%.+\\discretionary50%| replacing $") then local prefix = boxprefix(lastline) - if string.match(line, prefix .. "%.") or - string.match(line, prefix .. "%|") then - if string.match(lastline, " replacing $") and + if match(line, prefix .. "%.") or + match(line, prefix .. "%|") then + if match(lastline, " replacing $") and not dropping then -- Modify the return line - return string.gsub(line, "^%.", ""), lastline, true + return gsub(line, "^%.", ""), lastline, true else return "", lastline, true end @@ -986,11 +997,11 @@ function formatlualog(logfile, newfile) return line, "" else -- Not quite a normal discretionary - if string.match(lastline, "^%.+\\discretionary50%|$") then - lastline = string.gsub(lastline, "50%|$", "") + if match(lastline, "^%.+\\discretionary50%|$") then + lastline = gsub(lastline, "50%|$", "") end -- Remove some info that TeX90 lacks - lastline = string.gsub(lastline, " %(penalty 50%)$", "") + lastline = gsub(lastline, " %(penalty 50%)$", "") -- A normal (TeX90) discretionary: -- add with the line break reintroduced return lastline .. os_newline .. line, "" @@ -999,13 +1010,13 @@ function formatlualog(logfile, newfile) end -- Look for another form of \discretionary, replacing a "-" pattern = "^%.+\\discretionary replacing *$" - if string.match(line, pattern) then + if match(line, pattern) then return "", line else - if string.match(lastline, pattern) then + if match(lastline, pattern) then local prefix = boxprefix(lastline) - if string.match(line, prefix .. "%.\\kern") then - return string.gsub(line, "^%.", ""), lastline, true + if match(line, prefix .. "%.\\kern") then + return gsub(line, "^%.", ""), lastline, true elseif dropping then return "", "" else @@ -1015,26 +1026,26 @@ function formatlualog(logfile, newfile) end -- For \mathon, if the current line is an empty \hbox then -- drop it - if string.match(lastline, "^%.+\\mathon$") then + if match(lastline, "^%.+\\mathon$") then local prefix = boxprefix(lastline) - if string.match(line, prefix .. "\\hbox%(0%.0%+0%.0%)x0%.0$") then + if match(line, prefix .. "\\hbox%(0%.0%+0%.0%)x0%.0$") then return "", "" end end -- Various \local... things that other engines do not do: -- Only remove the no-op versions - if string.match(line, "^%.+\\localpar$") or - string.match(line, "^%.+\\localinterlinepenalty=0$") or - string.match(line, "^%.+\\localbrokenpenalty=0$") or - string.match(line, "^%.+\\localleftbox=null$") or - string.match(line, "^%.+\\localrightbox=null$") then + if match(line, "^%.+\\localpar$") or + match(line, "^%.+\\localinterlinepenalty=0$") or + match(line, "^%.+\\localbrokenpenalty=0$") or + match(line, "^%.+\\localleftbox=null$") or + match(line, "^%.+\\localrightbox=null$") then return "", "" end -- Older LuaTeX versions set the above up as a whatsit -- (at some stage this can therefore go) - if string.match(lastline, "^%.+\\whatsit$") then + if match(lastline, "^%.+\\whatsit$") then local prefix = boxprefix(lastline) - if string.match(line, prefix .. "%.") then + if match(line, prefix .. "%.") then return "", lastline, true else -- End of a \whatsit block @@ -1044,44 +1055,44 @@ function formatlualog(logfile, newfile) -- Wrap some cases that can be picked out -- In some places LuaTeX does use max_print_line, then we -- get into issues with different wrapping approaches - if string.len(line) == maxprintline then + if len(line) == maxprintline then return "", lastline .. line - elseif string.len(lastline) == maxprintline then - if string.match(line, "\\ETC%.%}$") then + elseif len(lastline) == maxprintline then + if match(line, "\\ETC%.%}$") then -- If the line wrapped at \ETC we might have lost a space return lastline - .. ((string.match(line, "^\\ETC%.%}$") and " ") or "") + .. ((match(line, "^\\ETC%.%}$") and " ") or "") .. line, "" - elseif string.match(line, "^%}%}%}$") then + elseif match(line, "^%}%}%}$") then return lastline .. line, "" else return lastline .. os_newline .. line, "" end -- Return all of the text for a wrapped (multi)line - elseif string.len(lastline) > maxprintline then + elseif len(lastline) > maxprintline then return lastline .. line, "" end -- Remove spaces at the start of lines: deals with the fact that LuaTeX -- uses a different number to the other engines - return string.gsub(line, "^%s+", ""), "" + return gsub(line, "^%s+", ""), "" end local newlog = "" local lastline = "" local dropping = false -- Read the entire log file as a binary: deals with ^@/^[, etc. - local file = assert(io.open(logfile, "rb")) - local contents = string.gsub(file:read("*all") .. "\n", "\r\n", "\n") - io.close(file) - for line in string.gmatch(contents, "([^\n]*)\n") do + local file = assert(open(logfile, "rb")) + local contents = gsub(file:read("*all") .. "\n", "\r\n", "\n") + close(file) + for line in gmatch(contents, "([^\n]*)\n") do line, lastline, dropping = normalize(line, lastline, dropping) - if not string.match(line, "^ *$") then + if not match(line, "^ *$") then newlog = newlog .. line .. os_newline end end - local newfile = io.open(newfile, "w") - io.output(newfile) - io.write(newlog) - io.close(newfile) + local newfile = open(newfile, "w") + output(newfile) + write(newlog) + close(newfile) end -- Look for files, directory by directory, and return the first existing @@ -1100,13 +1111,13 @@ end function listmodules() local modules = { } local exclmodules = exclmodules or { } - for entry in lfs.dir(".") do + for entry in lfs_dir(".") do if entry ~= "." and entry ~= ".." then - local attr = lfs.attributes(entry) + local attr = lfs_attributes(entry) assert(type(attr) == "table") if attr.mode == "directory" then if not exclmodules[entry] then - table.insert(modules, entry) + insert(modules, entry) end end end @@ -1167,7 +1178,7 @@ function setup_check(name, engine) "Error: failed to find " .. pdfext .. ", " .. tlgext .. " or " .. lveext .. " file for " .. name .. "!" ) - os.exit(1) + exit(1) end runtest(name, engine, true, lveext, true) pdffile = testdir .. "/" .. testname .. pdfext @@ -1181,19 +1192,19 @@ function setup_check(name, engine) for _,v in pairs({pdffile, tlgfile}) do if v then cp( - string.match(v, ".*/(.*)"), - string.match(v, "(.*)/.*"), + match(v, ".*/(.*)"), + match(v, "(.*)/.*"), testdir ) end end end if pdffile then - local pdffile = string.match(pdffile, ".*/(.*)") + local pdffile = match(pdffile, ".*/(.*)") ren( testdir, pdffile, - string.gsub(pdffile, pdfext .. "$", ".ref" .. pdfext) + gsub(pdffile, pdfext .. "$", ".ref" .. pdfext) ) return true else @@ -1212,14 +1223,14 @@ function compare_pdf(name, engine) if not refpdffile then return end - if os_windows then + if os_type == "windows" then refpdffile = unix_to_win(refpdffile) end - errorlevel = os.execute( + errorlevel = execute( os_cmpexe .. " " .. refpdffile .. " " .. pdffile .. " > " .. cmpfile ) if errorlevel == 0 then - os.remove(cmpfile) + os_remove(cmpfile) end return errorlevel end @@ -1233,18 +1244,18 @@ function compare_tlg(name, engine) if not tlgfile then return end - if os_windows then + if os_type == "windows" then tlgfile = unix_to_win(tlgfile) end -- Do additional log formatting if the engine is LuaTeX, there is no -- LuaTeX-specific .tlg file and the default engine is not LuaTeX if engine == "luatex" - and not string.match(tlgfile, "%.luatex" .. "%" .. tlgext) + and not match(tlgfile, "%.luatex" .. "%" .. tlgext) and stdengine ~= "luatex" and stdengine ~= "luajittex" then local luatlgfile = testdir .. "/" .. name .. ".luatex" .. tlgext - if os_windows then + if os_type == "windows" then luatlgfile = unix_to_win(luatlgfile) end formatlualog(tlgfile, luatlgfile) @@ -1252,11 +1263,11 @@ function compare_tlg(name, engine) -- This allows code sharing below: we only need the .tlg name in one place tlgfile = luatlgfile end - errorlevel = os.execute( + errorlevel = execute( os_diffexe .. " " .. tlgfile .. " " .. logfile .. " > " .. difffile ) if errorlevel == 0 then - os.remove(difffile) + os_remove(difffile) end return errorlevel end @@ -1272,31 +1283,31 @@ function runtest(name, engine, hide, ext, makepdf) local realengine = engine local format if - string.match(checkformat, "tex$") and - not string.match(engine, checkformat) then - format = " -fmt=" .. string.gsub(engine, "(.*)tex$", "%1") .. checkformat + match(checkformat, "tex$") and + not match(engine, checkformat) then + format = " -fmt=" .. gsub(engine, "(.*)tex$", "%1") .. checkformat else format = "" end -- Special casing for e-LaTeX format if - string.match(checkformat, "^latex$") and - string.match(engine, "^etex$") then + match(checkformat, "^latex$") and + match(engine, "^etex$") then format = " -fmt=latex" end -- Special casing for (u)pTeX LaTeX formats if - string.match(checkformat, "^latex$") and - string.match(engine, "^u?ptex$") then + match(checkformat, "^latex$") and + match(engine, "^u?ptex$") then realengine = "e" .. engine end -- Special casing for XeTeX engine local checkopts = checkopts - if string.match(engine, "xetex") and not makepdf then + if match(engine, "xetex") and not makepdf then checkopts = checkopts .. " -no-pdf" end -- Special casing for ConTeXt - if string.match(checkformat, "^context$") then + if match(checkformat, "^context$") then format = "" if engine == "luatex" or engine == "luajittex" then realengine = "context" @@ -1306,7 +1317,7 @@ function runtest(name, engine, hide, ext, makepdf) realengine = "texexec --xetex" else print("Engine incompatible with format") - os.exit(1) + exit(1) end end local logfile = testdir .. "/" .. name .. logext @@ -1349,12 +1360,12 @@ function runtest(name, engine, hide, ext, makepdf) formatlog(logfile, newfile, engine) -- Store secondary files for this engine for _,i in ipairs(filelist(testdir, name .. ".???")) do - local ext = string.match(i, "%....") + local ext = match(i, "%....") if ext ~= lvtext and ext ~= tlgext and ext ~= lveext and ext ~= logext then if not fileexists(testsuppdir .. "/" .. i) then ren( - testdir, i, string.gsub( - i, string.gsub(name, "%-", "%%-"), name .. "." .. engine + testdir, i, gsub( + i, gsub(name, "%-", "%%-"), name .. "." .. engine ) ) end @@ -1368,7 +1379,7 @@ runtest_tasks = runtest_tasks or function(name) end function dvitopdf(name, dir, engine, hide) - if string.match(engine, "^u?ptex$") then + if match(engine, "^u?ptex$") then run( dir, os_setenv .. " SOURCE_DATE_EPOCH=" .. epoch @@ -1392,7 +1403,13 @@ end -- Strip the extension from a file name (if present) function stripext(file) - local name = string.match(file, "^(.*)%.") + local name = match(file, "^(.*)%.") + return name or file +end + +-- Strip the path from a file name (if present) +function basename(file) + local name = match(file, "^.*/([^/]*)$") return name or file end @@ -1411,7 +1428,7 @@ function runtool(envvar, command) run( typesetdir, os_setenv .. " " .. envvar .. "=." .. os_pathsep - .. relpath(localdir, typesetdir) + .. abspath(localdir) .. (typesetsearch and os_pathsep or "") .. os_concat .. command @@ -1433,7 +1450,7 @@ function bibtex(name) -- LaTeX always generates an .aux file, so there is a need to -- look inside it for a \citation line local grep - if os_windows then + if os_type == "windows" then grep = "\\\\" else grep = "\\\\\\\\" @@ -1452,7 +1469,7 @@ function bibtex(name) runtool( "BIBINPUTS", os_setenv .. " BSTINPUTS=." .. os_pathsep - .. relpath(localdir, typesetdir) + .. abspath(localdir) .. (typesetsearch and os_pathsep or "") .. os_concat .. bibtexexe .. " " .. bibtexopts .. " " .. name @@ -1488,11 +1505,11 @@ function tex(file) end function typesetpdf(file) - local name = stripext(file) + local name = stripext(basename(file)) print("Typesetting " .. name) local errorlevel = typeset(file) if errorlevel == 0 then - os.remove(name .. ".pdf") + os_remove(name .. ".pdf") cp(name .. ".pdf", typesetdir, ".") else print(" ! Compilation failed") @@ -1505,7 +1522,7 @@ typeset = typeset or function(file) if errorlevel ~= 0 then return errorlevel else - local name = stripext(file) + local name = stripext(basename(file)) errorlevel = biber(name) + bibtex(name) if errorlevel == 0 then local function cycle(name) @@ -1572,14 +1589,14 @@ function check(names) -- No names passed: find all test files if not next(names) then for _,i in pairs(filelist(testfiledir, "*" .. lvtext)) do - table.insert(names, stripext(i)) + insert(names, stripext(i)) end for _,i in ipairs(filelist(unpackdir, "*" .. lvtext)) do if fileexists(testfiledir .. "/" .. i) then print("Duplicate test file: " .. i) return 1 else - table.insert(names, stripext(i)) + insert(names, stripext(i)) end end end @@ -1623,7 +1640,7 @@ function showfaileddiff() for _,i in ipairs(filelist(testdir, "*" .. os_diffext)) do print(" - " .. testdir .. "/" .. i) print("") - local f = io.open(testdir .. "/" .. i,"r") + local f = open(testdir .. "/" .. i,"r") local content = f:read("*all") f:close() print("-----------------------------------------------------------------------------------") @@ -1678,8 +1695,8 @@ function cmdcheck() for _,i in ipairs(typesetsuppfiles) do cp(i, supportdir, testdir) end - local engine = string.gsub(stdengine, "tex$", "latex") - local localdir = relpath(localdir, testdir) + local engine = gsub(stdengine, "tex$", "latex") + local localdir = abspath(localdir) print("Checking source files") for _,i in ipairs(cmdchkfiles) do for _,j in ipairs(filelist(".", i)) do @@ -1693,9 +1710,9 @@ function cmdcheck() " \"\\PassOptionsToClass{check}{l3doc} \\input " .. j .. "\"" .. " > " .. os_null ) - for line in io.lines(testdir .. "/" .. stripext(j) .. ".cmds") do - if string.match(line, "^%!") then - print(" - " .. string.match(line, "^%! (.*)")) + for line in lines(testdir .. "/" .. stripext(j) .. ".cmds") do + if match(line, "^%!") then + print(" - " .. match(line, "^%! (.*)")) end end end @@ -1793,7 +1810,7 @@ function bundlectan() for _,i in ipairs(include) do for _,j in ipairs(filelist(".", i)) do if not excludelist[j] then - table.insert(includelist, j) + insert(includelist, j) end end end @@ -1805,7 +1822,7 @@ function bundlectan() -- Work out what PDF files are available pdffiles = { } for _,i in ipairs(typesetfiles) do - table.insert(pdffiles, (string.gsub(i, "%.%w+$", ".pdf"))) + insert(pdffiles, (gsub(i, "%.%w+$", ".pdf"))) end typesetlist = excludelist(typesetfiles, {sourcefiles}) sourcelist = excludelist( @@ -1834,22 +1851,24 @@ function doc(files) unpack() -- Main loop for doc creation for _,i in ipairs(typesetfiles) do - for _,j in ipairs(filelist(".", i)) do - -- Allow for command line selection of files - local typeset = true - if files and next(files) then - typeset = false - for _,k in ipairs(files) do - if k == stripext(j) then - typeset = true - break + for _, dir in ipairs({unpackdir, typesetdir}) do + for _,j in ipairs(filelist(dir, i)) do + -- Allow for command line selection of files + local typeset = true + if files and next(files) then + typeset = false + for _,k in ipairs(files) do + if k == stripext(j) then + typeset = true + break + end end end - end - if typeset then - local errorlevel = typesetpdf(j) - if errorlevel ~= 0 then - return errorlevel + if typeset then + local errorlevel = typesetpdf(abspath(dir) .. "/" .. j) + if errorlevel ~= 0 then + return errorlevel + end end end end @@ -1863,8 +1882,8 @@ function install() if errorlevel ~= 0 then return errorlevel end - kpse.set_program_name("latex") - local texmfhome = kpse.var_value("TEXMFHOME") + set_program_name("latex") + local texmfhome = var_value("TEXMFHOME") local installdir = texmfhome .. "/tex/" .. moduledir errorlevel = cleandir(installdir) if errorlevel ~= 0 then @@ -1928,13 +1947,13 @@ if versionform ~= "" and not setversion_update_line then function setversion_update_line(line, date, release) -- No real regex so do it one type at a time for _,i in pairs({"Class", "File", "Package"}) do - if string.match( + if match( line, "^\\Provides" .. i .. "{[a-zA-Z0-9%-%.]+}%[[^%]]*%]$" ) then - line = string.gsub(line, "%[%d%d%d%d/%d%d/%d%d", "[" - .. string.gsub(date, "%-", "/")) - line = string.gsub( + line = gsub(line, "%[%d%d%d%d/%d%d/%d%d", "[" + .. gsub(date, "%-", "/")) + line = gsub( line, "(%[%d%d%d%d/%d%d/%d%d) [^ ]*", "%1 " .. release ) break @@ -1946,14 +1965,14 @@ if versionform ~= "" and not setversion_update_line then function setversion_update_line(line, date, release) -- No real regex so do it one type at a time for _,i in pairs({"Class", "File", "Package"}) do - if string.match( + if match( line, "^\\ProvidesExpl" .. i .. " *{[a-zA-Z0-9%-%.]+}" ) then - line = string.gsub( + line = gsub( line, "{%d%d%d%d/%d%d/%d%d}( *){[^}]*}", - "{" .. string.gsub(date, "%-", "/") .. "}%1{" .. release .. "}" + "{" .. gsub(date, "%-", "/") .. "}%1{" .. release .. "}" ) break end @@ -1962,20 +1981,20 @@ if versionform ~= "" and not setversion_update_line then end elseif versionform == "filename" then function setversion_update_line(line, date, release) - if string.match(line, "^\\def\\filedate{%d%d%d%d/%d%d/%d%d}$") then - line = "\\def\\filedate{" .. string.gsub(date, "%-", "/") .. "}" + if match(line, "^\\def\\filedate{%d%d%d%d/%d%d/%d%d}$") then + line = "\\def\\filedate{" .. gsub(date, "%-", "/") .. "}" end - if string.match(line, "^\\def\\fileversion{[^}]+}$") then + if match(line, "^\\def\\fileversion{[^}]+}$") then line = "\\def\\fileversion{" .. release .. "}" end return line end elseif versionform == "ExplFileDate" then function setversion_update_line(line, date, release) - if string.match(line, "^\\def\\ExplFileDate{%d%d%d%d/%d%d/%d%d}$") then - line = "\\def\\ExplFileDate{" .. string.gsub(date, "%-", "/") .. "}" + if match(line, "^\\def\\ExplFileDate{%d%d%d%d/%d%d/%d%d}$") then + line = "\\def\\ExplFileDate{" .. gsub(date, "%-", "/") .. "}" end - if string.match(line, "^\\def\\ExplFileVersion{[^}]+}$") then + if match(line, "^\\def\\ExplFileVersion{[^}]+}$") then line = "\\def\\ExplFileVersion{" .. release .. "}" end return line @@ -1988,36 +2007,36 @@ setversion_update_line = setversion_update_line or function(line, date, release) return line end -function setversion() - local function rewrite(file, date, version) +function setversion(dir) + local function rewrite(dir, file, date, release) local changed = false - local lines = "" - for line in io.lines(file) do - local newline = setversion_update_line(line, date, version) + local result = "" + for line in lines(dir .. "/" .. file) do + local newline = setversion_update_line(line, date, release) if newline ~= line then line = newline changed = true end - lines = lines .. line .. os_newline + result = result .. line .. os_newline end if changed then -- Avoid adding/removing end-of-file newline - local f = io.open(file, "rb") + local f = open(dir .. "/" .. file, "rb") local content = f:read("*all") - io.close(f) - if not string.match(content, os_newline .. "$") then - string.gsub(lines, os_newline .. "$", "") + close(f) + if not match(content, os_newline .. "$") then + gsub(result, os_newline .. "$", "") end -- Write the new file - ren(".", file, file .. bakext) - local f = io.open(file, "w") - io.output(f) - io.write(lines) - io.close(f) - rm(".", file .. bakext) + ren(dir, file, file .. bakext) + local f = open(dir .. "/" .. file, "w") + output(f) + write(result) + close(f) + rm(dir, file .. bakext) end end - local date = os.date("%Y-%m-%d") + local date = os_date("%Y-%m-%d") if optdate then date = optdate[1] or date end @@ -2025,9 +2044,10 @@ function setversion() if optrelease then release = optrelease[1] or release end + local dir = dir or "." for _,i in pairs(versionfiles) do - for _,j in pairs(filelist(".", i)) do - rewrite(j, date, release) + for _,j in pairs(filelist(dir, i)) do + rewrite(dir, j, date, release) end end return 0 @@ -2083,10 +2103,10 @@ bundleunpack = bundleunpack or function(sourcedir) -- This 'yes' business is needed to pass a series of "y\n" to -- TeX if \askforoverwrite is true -- That is all done using a file as it's the only way on Windows and - -- on Unix the "yes" command can't be used inside os.execute (it never + -- on Unix the "yes" command can't be used inside execute (it never -- stops, which confuses Lua) - os.execute(os_yes .. ">>" .. localdir .. "/yes") - local localdir = relpath(localdir, unpackdir) + execute(os_yes .. ">>" .. localdir .. "/yes") + local localdir = abspath(localdir) errorlevel = run( unpackdir, os_setenv .. " TEXINPUTS=." .. os_pathsep @@ -2107,7 +2127,7 @@ end function version() print( "\n" - .. "l3build Release " .. string.gsub(release_date, "/", "-") .. "\n" + .. "l3build Release " .. gsub(release_date, "/", "-") .. "\n" ) end @@ -2187,9 +2207,9 @@ function stdmain(target, files) end end if errorlevel ~= 0 then - os.exit(1) + exit(1) else - os.exit(0) + exit(0) end end @@ -2197,9 +2217,9 @@ end main = main or stdmain -- Pick up and read any per-run testfiledir -if userargs["testfiledir"] then - if #userargs["testfiledir"] == 1 then - testfiledir = userargs["testfiledir"][1] +if options["testfiledir"] then + if #options["testfiledir"] == 1 then + testfiledir = options["testfiledir"][1] if fileexists(testfiledir .. "/config.lua") then dofile(testfiledir .. "/config.lua") end @@ -2210,4 +2230,4 @@ if userargs["testfiledir"] then end -- Call the main function -main(userargs["target"], userargs["files"]) +main(options["target"], options["files"]) diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3intarray.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3intarray.sty new file mode 100644 index 00000000000..8239e693bbc --- /dev/null +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3intarray.sty @@ -0,0 +1,104 @@ +%% +%% This is file `l3intarray.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3intarray.dtx (with options: `package') +%% +%% Copyright (C) 2011-2017 The LaTeX3 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 "l3experimental bundle" (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% File: l3intarray.dtx Copyright (C) 2017 The LaTeX3 Project +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} + {} + {% + \PackageError{l3intarray}{Support package l3kernel too old} + {% + Please install an up to date version of l3kernel\MessageBreak + using your TeX package manager or from CTAN.\MessageBreak + \MessageBreak + Loading l3intarray will abort!% + }% + \endinput + } +\ProvidesExplPackage{l3intarray}{2017/05/13}{} + {L3 Experimental low-level arrays of small integers} +\int_new:N \g__intarray_font_int +\cs_new_protected:Npn \__intarray_new:Nn #1#2 + { + \__chk_if_free_cs:N #1 + \int_gincr:N \g__intarray_font_int + \tex_global:D \tex_font:D #1 = cmr10~at~ \g__intarray_font_int sp \scan_stop: + \tex_hyphenchar:D #1 = \int_eval:n {#2} \scan_stop: + \int_compare:nNnT { \tex_hyphenchar:D #1 } > 0 + { \tex_fontdimen:D \tex_hyphenchar:D #1 #1 = 0 sp \scan_stop: } + \int_step_inline:nnnn { 1 } { 1 } { 8 } + { \tex_fontdimen:D ##1 #1 = 0 sp \scan_stop: } + } +\cs_new:Npn \__intarray_count:N #1 { \tex_the:D \tex_hyphenchar:D #1 } +\cs_new_protected:Npn \__intarray_gset_fast:Nnn #1#2#3 + { \tex_fontdimen:D \int_eval:n {#2} #1 = \int_eval:n {#3} sp \scan_stop: } +\cs_new_protected:Npn \__intarray_gset:Nnn #1#2#3 + { + \exp_args:Nff \__intarray_gset_aux:Nnn #1 + { \int_eval:n {#2} } { \int_eval:n {#3} } + } +\cs_new_protected:Npn \__intarray_gset_aux:Nnn #1#2#3 + { + \int_compare:nTF { 1 <= #2 <= \__intarray_count:N #1 } + { + \int_compare:nTF { - \c_max_dim <= \int_abs:n {#3} <= \c_max_dim } + { \__intarray_gset_fast:Nnn #1 {#2} {#3} } + { + \__msg_kernel_error:nnxxxx { intarray } { overflow } + { \token_to_str:N #1 } {#2} {#3} + { \int_compare:nNnT {#3} < 0 { - } \__int_value:w \c_max_dim } + \__intarray_gset_fast:Nnn #1 {#2} + { \int_compare:nNnT {#3} < 0 { - } \c_max_dim } + } + } + { + \__msg_kernel_error:nnxxx { intarray } { out-of-bounds } + { \token_to_str:N #1 } {#2} { \__intarray_count:N #1 } + } + } +\cs_new:Npn \__intarray_item_fast:Nn #1#2 + { \__int_value:w \tex_fontdimen:D \int_eval:n {#2} #1 } +\cs_new:Npn \__intarray_item:Nn #1#2 + { \exp_args:Nf \__intarray_item_aux:Nn #1 { \int_eval:n {#2} } } +\cs_new:Npn \__intarray_item_aux:Nn #1#2 + { + \int_compare:nTF { 1 <= #2 <= \__intarray_count:N #1 } + { \__intarray_item_fast:Nn #1 {#2} } + { + \__msg_kernel_expandable_error:nnnnn { intarray } { out-of-bounds } + { \token_to_str:N #1 } {#2} { \__intarray_count:N #1 } + 0 + } + } +\__msg_kernel_new:nnnn { intarray } { overflow } + { Integers~larger~than~2^{30}-1~cannot~be~stored~in~arrays. } + { + An~attempt~was~made~to~store~#3~at~position~#2~in~the~array~'#1'.~ + The~largest~allowed~value~#4~will~be~used~instead. + } +\__msg_kernel_new:nnnn { intarray } { out-of-bounds } + { Access~to~an~entry~beyond~an~array's~bounds. } + { + An~attempt~was~made~to~access~or~store~data~at~position~#2~of~the~ + array~'#1',~but~this~array~has~entries~at~positions~from~1~to~#3. + } +%% +%% +%% End of file `l3intarray.sty'. diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty index e74c484390d..abb10d12edf 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex-trace.sty @@ -6,7 +6,7 @@ %% %% l3regex.dtx (with options: `package,trace') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of @@ -19,8 +19,8 @@ %% and all files in that bundle must be distributed together. %% %% File: l3regex.dtx Copyright (C) 2011-2017 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{l3regex}{Support package l3kernel too old} @@ -32,10 +32,46 @@ }% \endinput } -\ProvidesExplPackage{l3regex}{2017/04/01}{} +\ProvidesExplPackage{l3regex}{2017/05/13}{} {L3 Experimental regular expressions} -\RequirePackage{l3tl-build, l3tl-analysis, l3str-convert} +\RequirePackage{l3tl-build, l3tl-analysis, l3intarray} \cs_generate_variant:Nn \tl_to_str:n { V } +\cs_new_protected:Npn \__regex_standard_escapechar: + { \int_set:Nn \tex_escapechar:D { `\\ } } +\cs_new:Npn \__regex_toks_use:w { \tex_the:D \tex_toks:D } +\cs_new_protected:Npn \__regex_toks_clear:N #1 + { \tex_toks:D #1 { } } +\cs_new_eq:NN \__regex_toks_set:Nn \tex_toks:D +\cs_new_protected:Npn \__regex_toks_set:No #1 + { \__regex_toks_set:Nn #1 \exp_after:wN } +\cs_new_protected:Npn \__regex_toks_memcpy:NNn #1#2#3 + { + \prg_replicate:nn {#3} + { + \tex_toks:D #1 = \tex_toks:D #2 + \int_incr:N #1 + \int_incr:N #2 + } + } +\cs_new_protected:Npn \__regex_toks_put_left:Nx #1#2 + { + \cs_set:Npx \__regex_tmp:w { #2 } + \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN + { \exp_after:wN \__regex_tmp:w \tex_the:D \tex_toks:D #1 } + } +\cs_new_protected:Npn \__regex_toks_put_right:Nx #1#2 + { + \cs_set:Npx \__regex_tmp:w {#2} + \tex_toks:D #1 \exp_after:wN + { \tex_the:D \tex_toks:D \exp_after:wN #1 \__regex_tmp:w } + } +\cs_new_protected:Npn \__regex_toks_put_right:Nn #1#2 + { \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D #1 #2 } } +\cs_new:Npn \__regex_current_cs_to_str: + { + \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N + \tex_the:D \tex_toks:D \l__regex_current_pos_int + } \cs_new:Npn \__regex_tmp:w { } \tl_new:N \l__regex_internal_a_tl \tl_new:N \l__regex_internal_b_tl @@ -50,8 +86,15 @@ \__regex_branch:n { \__regex_class:NnnnN \c_true_bool { } { 1 } { 0 } \c_true_bool } } +\__intarray_new:Nn \g__regex_charcode_intarray { 65536 } +\__intarray_new:Nn \g__regex_catcode_intarray { 65536 } +\__intarray_new:Nn \g__regex_balance_intarray { 65536 } \int_new:N \l__regex_balance_int \tl_new:N \l__regex_cs_name_tl +\int_const:Nn \c__regex_ascii_min_int { 0 } +\int_const:Nn \c__regex_ascii_max_control_int { 31 } +\int_const:Nn \c__regex_ascii_max_int { 127 } +\int_const:Nn \c__regex_ascii_lower_int { `a - `A } \cs_new_protected:Npn \__regex_break_true:w #1 \__regex_break_point:TF #2 #3 {#2} \cs_new_protected:Npn \__regex_break_point:TF #1 #2 { #2 } @@ -108,12 +151,12 @@ \if_int_compare:w \l__regex_current_char_int > `Z \exp_stop_f: \if_int_compare:w \l__regex_current_char_int > `z \exp_stop_f: \else: \if_int_compare:w \l__regex_current_char_int < `a \exp_stop_f: \else: - \int_sub:Nn \l__regex_case_changed_char_int { \c__str_ascii_lower_int } + \int_sub:Nn \l__regex_case_changed_char_int { \c__regex_ascii_lower_int } \fi: \fi: \else: \if_int_compare:w \l__regex_current_char_int < `A \exp_stop_f: \else: - \int_add:Nn \l__regex_case_changed_char_int { \c__str_ascii_lower_int } + \int_add:Nn \l__regex_case_changed_char_int { \c__regex_ascii_lower_int } \fi: \fi: } @@ -152,12 +195,7 @@ \int_compare:nNnTF \l__regex_current_catcode_int = 0 { \tl_set:Nx \l__regex_internal_a_tl - { - \scan_stop: - \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N - \tex_the:D \tex_toks:D \l__regex_current_pos_int - \scan_stop: - } + { \scan_stop: \__regex_current_cs_to_str: \scan_stop: } \tl_if_in:noTF { \scan_stop: #1 \scan_stop: } \l__regex_internal_a_tl { \__regex_break_true:w } { } } @@ -168,12 +206,7 @@ \int_compare:nNnT \l__regex_current_catcode_int = 0 { \group_begin: - \tl_set:Nx \l__regex_cs_name_tl - { - \exp_after:wN \exp_after:wN - \exp_after:wN \cs_to_str:N - \tex_the:D \tex_toks:D \l__regex_current_pos_int - } + \tl_set:Nx \l__regex_cs_name_tl { \__regex_current_cs_to_str: } \__regex_single_match: \__regex_disable_submatches: \__regex_build_for_cs:n {#1} @@ -222,16 +255,16 @@ \cs_new_protected:Npn \__regex_posix_ascii: { \__regex_item_caseful_range:nn - \c__str_ascii_min_int - \c__str_ascii_max_int + \c__regex_ascii_min_int + \c__regex_ascii_max_int } \cs_new_eq:NN \__regex_posix_blank: \__regex_prop_h: \cs_new_protected:Npn \__regex_posix_cntrl: { \__regex_item_caseful_range:nn - \c__str_ascii_min_int - \c__str_ascii_max_control_int - \__regex_item_caseful_equal:n \c__str_ascii_max_int + \c__regex_ascii_min_int + \c__regex_ascii_max_control_int + \__regex_item_caseful_equal:n \c__regex_ascii_max_int } \cs_new_eq:NN \__regex_posix_digit: \__regex_prop_d: \cs_new_protected:Npn \__regex_posix_graph: @@ -268,8 +301,8 @@ \cs_set:Npn \__regex_escape_unescaped:N ##1 { #1 } \cs_set:Npn \__regex_escape_escaped:N ##1 { #2 } \cs_set:Npn \__regex_escape_raw:N ##1 { #3 } - \int_set:Nn \tex_escapechar:D { `\\ } - \__str_gset_other:Nn \g__regex_internal_tl { #4 } + \__regex_standard_escapechar: + \tl_gset:Nx \g__regex_internal_tl { \__str_to_other_fast:n {#4} } \tl_set:Nx \l__regex_internal_b_tl { \exp_after:wN \__regex_escape_loop:N \g__regex_internal_tl @@ -323,36 +356,19 @@ } \cs_new:Npn \__regex_escape_x_end:w #1 ; { - \int_compare:nNnTF {#1} > \c__str_max_byte_int - { \__regex_escape_x_large:n {#1} } + \int_compare:nNnTF {#1} > \c_max_char_int + { + \if_false: { \fi: } + \__tl_build_one:o \l__regex_internal_b_tl + \__msg_kernel_error:nnx { regex } { x-overflow } {#1} + \tl_set:Nx \l__regex_internal_b_tl + { \if_false: } \fi: + } { \exp_last_unbraced:Nf \__regex_escape_raw:N - { \__str_output_byte:n {#1} } + { \char_generate:nn {#1} { 12 } } } } -\group_begin: - \char_set_catcode_other:n { 0 } - \cs_new:Npn \__regex_escape_x_large:n #1 - { - \if_false: { \fi: } - \__tl_build_one:o \l__regex_internal_b_tl - \int_compare:nNnTF {#1} > \c_max_char_int - { - \__msg_kernel_error:nnx { regex } { x-overflow } {#1} - \tl_set:Nx \l__regex_internal_b_tl - { \if_false: } \fi: - } - { - \char_set_lccode:nn { 0 } {#1} - \tex_lowercase:D - { - \tl_set:Nx \l__regex_internal_b_tl - { \if_false: } \fi: - \__regex_escape_raw:N ^^@ - } - } - } -\group_end: \cs_new:Npn \__regex_escape_x_test:N #1 { \str_if_eq_x:nnTF {#1} { break } { ; } @@ -370,7 +386,7 @@ \if_charcode:w \c_left_brace_str #1 \exp_after:wN \__regex_escape_x_loop:N \else: - \__str_hexadecimal_use:NTF #1 + \__regex_hexadecimal_use:NTF #1 { \exp_after:wN \__regex_escape_x:N } { ; \exp_after:wN \__regex_escape_loop:N \exp_after:wN #1 } \fi: @@ -379,7 +395,7 @@ { \str_if_eq_x:nnTF {#1} { break } { ; } { - \__str_hexadecimal_use:NTF #1 + \__regex_hexadecimal_use:NTF #1 { ; \__regex_escape_loop:N } { ; \__regex_escape_loop:N #1 } } @@ -389,7 +405,7 @@ \str_if_eq_x:nnTF {#1} { break } { ; \__regex_escape_x_loop_error:n { } {#1} } { - \__str_hexadecimal_use:NTF #1 + \__regex_hexadecimal_use:NTF #1 { \__regex_escape_x_loop:N } { \token_if_eq_charcode:NNTF \c_space_token #1 @@ -412,11 +428,32 @@ \tl_set:Nx \l__regex_internal_b_tl { \if_false: } \fi: \__regex_escape_loop:N #1 } +\prg_new_conditional:Npnn \__regex_hexadecimal_use:N #1 { TF } + { + \if_int_compare:w 1 < "1 \token_to_str:N #1 \exp_stop_f: + #1 \prg_return_true: + \else: + \if_case:w \__int_eval:w + \exp_after:wN ` \token_to_str:N #1 - `a + \__int_eval_end: + A + \or: B + \or: C + \or: D + \or: E + \or: F + \else: + \prg_return_false: + \exp_after:wN \use_none:n + \fi: + \prg_return_true: + \fi: + } \prg_new_conditional:Npnn \__regex_char_if_special:N #1 { TF } { \if_int_compare:w `#1 > `Z \exp_stop_f: \if_int_compare:w `#1 > `z \exp_stop_f: - \if_int_compare:w `#1 < \c__str_ascii_max_int + \if_int_compare:w `#1 < \c__regex_ascii_max_int \prg_return_true: \else: \prg_return_false: \fi: \else: \if_int_compare:w `#1 < `a \exp_stop_f: @@ -607,7 +644,7 @@ \cs_new_protected:Npn \__regex_compile:n #1 { \__regex_compile:w - \int_set:Nn \tex_escapechar:D { `\\ } + \__regex_standard_escapechar: \int_set_eq:NN \l__regex_mode_int \c__regex_outer_mode_int \__regex_escape_use:nnnn { @@ -1201,7 +1238,7 @@ { \if_int_odd:w \__int_eval:w \l__regex_catcodes_int / #1 \__int_eval_end: \else: - \tex_advance:D \l__regex_catcodes_int #1 + \int_add:Nn \l__regex_catcodes_int {#1} \fi: } \cs_new_protected:Npn \__regex_compile_c_lbrack_end: @@ -1329,8 +1366,8 @@ } \cs_new_protected:Npn \__regex_compile_u_in_cs: { - \exp_args:NNo \__str_gset_other:Nn \g__regex_internal_tl - { \l__regex_internal_a_tl } + \tl_gset:Nx \g__regex_internal_tl + { \exp_args:No \__str_to_other_fast:n { \l__regex_internal_a_tl } } \__tl_build_one:x { \tl_map_function:NN \g__regex_internal_tl @@ -1522,6 +1559,7 @@ { control~sequence~ \seq_use:Nn \l__regex_internal_seq { ~or~ } } } \int_new:N \l__regex_min_state_int +\int_set:Nn \l__regex_min_state_int { 1 } \int_new:N \l__regex_max_state_int \int_new:N \l__regex_left_state_int \int_new:N \l__regex_right_state_int @@ -1536,7 +1574,7 @@ \cs_new_protected:Npn \__regex_build:N #1 { \trace_push:nnn { regex } { 1 } { __regex_build } - \int_set:Nn \tex_escapechar:D { `\\ } + \__regex_standard_escapechar: \int_zero:N \l__regex_capturing_group_int \int_set_eq:NN \l__regex_max_state_int \l__regex_min_state_int \__regex_build_new_state: @@ -1581,20 +1619,6 @@ \seq_pop:NN \l__regex_right_state_seq \l__regex_internal_a_tl \int_set:Nn \l__regex_right_state_int \l__regex_internal_a_tl } -\cs_new_protected:Npn \__regex_toks_put_left:Nx #1#2 - { - \cs_set:Npx \__regex_tmp:w { #2 } - \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN - { \exp_after:wN \__regex_tmp:w \tex_the:D \tex_toks:D #1 } - } -\cs_new_protected:Npn \__regex_toks_put_right:Nx #1#2 - { - \cs_set:Npx \__regex_tmp:w {#2} - \tex_toks:D #1 \exp_after:wN - { \tex_the:D \tex_toks:D \exp_after:wN #1 \__regex_tmp:w } - } -\cs_new_protected:Npn \__regex_toks_put_right:Nn #1#2 - { \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D #1 #2 } } \cs_new_protected:Npn \__regex_build_transition_left:NNN #1#2#3 { \__regex_toks_put_left:Nx #2 { #1 { \int_eval:n { #3 - #2 } } } } \cs_new_protected:Npn \__regex_build_transition_right:nNn #1#2#3 @@ -1609,7 +1633,7 @@ M=\int_use:N \l__regex_max_state_int ~ -> ~ \int_eval:n { \l__regex_max_state_int + 1 } } - \tex_toks:D \l__regex_max_state_int { } + \__regex_toks_clear:N \l__regex_max_state_int \int_set_eq:NN \l__regex_left_state_int \l__regex_right_state_int \int_set_eq:NN \l__regex_right_state_int \l__regex_max_state_int \int_incr:N \l__regex_max_state_int @@ -1776,15 +1800,12 @@ ( #1 - 1 ) * ( \l__regex_internal_b_int - \l__regex_internal_a_int ) } - \tex_advance:D \l__regex_right_state_int \l__regex_internal_c_int - \tex_advance:D \l__regex_max_state_int \l__regex_internal_c_int - \prg_replicate:nn \l__regex_internal_c_int - { - \tex_toks:D \l__regex_internal_b_int - = \tex_toks:D \l__regex_internal_a_int - \int_incr:N \l__regex_internal_a_int - \int_incr:N \l__regex_internal_b_int - } + \int_add:Nn \l__regex_right_state_int { \l__regex_internal_c_int } + \int_add:Nn \l__regex_max_state_int { \l__regex_internal_c_int } + \__regex_toks_memcpy:NNn + \l__regex_internal_b_int + \l__regex_internal_a_int + \l__regex_internal_c_int \fi: } \cs_new_protected:Npn \__regex_group_repeat:nnN #1#2#3 @@ -1912,6 +1933,8 @@ \int_new:N \l__regex_step_int \int_new:N \l__regex_min_active_int \int_new:N \l__regex_max_active_int +\__intarray_new:Nn \g__regex_state_active_intarray { 65536 } +\__intarray_new:Nn \g__regex_thread_state_intarray { 65536 } \tl_new:N \l__regex_every_match_tl \bool_new:N \l__regex_fresh_thread_bool \bool_new:N \l__regex_empty_success_bool @@ -1935,12 +1958,13 @@ \bool_gset_false:N \g__regex_success_bool \int_step_inline:nnnn \l__regex_min_state_int { 1 } { \l__regex_max_state_int - 1 } - { \tex_dimen:D ##1 ~ 1 sp \scan_stop: } + { \__intarray_gset_fast:Nnn \g__regex_state_active_intarray {##1} { 1 } } \int_set_eq:NN \l__regex_min_active_int \l__regex_max_state_int \int_zero:N \l__regex_step_int \int_set_eq:NN \l__regex_success_pos_int \l__regex_min_pos_int - \int_set:Nn \l__regex_submatch_int + \int_set:Nn \l__regex_min_submatch_int { 2 * \l__regex_max_state_int } + \int_set_eq:NN \l__regex_submatch_int \l__regex_min_submatch_int \bool_set_false:N \l__regex_empty_success_bool \__regex_match_once: \trace_pop:nnx { regex } { 1 } { __regex_match } @@ -1982,7 +2006,7 @@ } \cs_new_protected:Npn \__regex_match_loop: { - \tex_advance:D \l__regex_step_int 2 \exp_stop_f: + \int_add:Nn \l__regex_step_int { 2 } \int_incr:N \l__regex_current_pos_int \int_set_eq:NN \l__regex_last_char_int \l__regex_current_char_int \int_set_eq:NN \l__regex_case_changed_char_int \c_max_int @@ -1990,8 +2014,11 @@ \use:x { \int_set_eq:NN \l__regex_max_active_int \l__regex_min_active_int - \exp_after:wN \__regex_match_one_active:w - \int_use:N \l__regex_min_active_int ; + \int_step_function:nnnN + { \l__regex_min_active_int } + { 1 } + { \l__regex_max_active_int - 1 } + \__regex_match_one_active:n } \__prg_break_point: \bool_set_false:N \l__regex_fresh_thread_bool %^^A was arg of break_point:n @@ -2001,25 +2028,21 @@ \fi: \fi: } -\cs_new:Npn \__regex_match_one_active:w #1; +\cs_new:Npn \__regex_match_one_active:n #1 { - \if_int_compare:w #1 < \l__regex_max_active_int - \__regex_use_state_and_submatches:nn - { \__int_value:w \tex_skip:D #1 } - { \tex_the:D \tex_toks:D #1 } - \exp_after:wN \__regex_match_one_active:w - \__int_value:w \__int_eval:w #1 + 1 \exp_after:wN ; - \fi: + \__regex_use_state_and_submatches:nn + { \__intarray_item_fast:Nn \g__regex_thread_state_intarray {#1} } + { \__regex_toks_use:w #1 } } \cs_new_protected:Npn \__regex_query_set:nnn #1#2#3 { - \tex_muskip:D \l__regex_current_pos_int - = \etex_gluetomu:D - #3 sp - plus #2 sp - minus \l__regex_balance_int sp - \scan_stop: - \tex_toks:D \l__regex_current_pos_int {#1} + \__intarray_gset_fast:Nnn \g__regex_charcode_intarray + { \l__regex_current_pos_int } {#3} + \__intarray_gset_fast:Nnn \g__regex_catcode_intarray + { \l__regex_current_pos_int } {#2} + \__intarray_gset_fast:Nnn \g__regex_balance_intarray + { \l__regex_current_pos_int } { \l__regex_balance_int } + \__regex_toks_set:Nn \l__regex_current_pos_int {#1} \int_incr:N \l__regex_current_pos_int \if_case:w #2 \exp_stop_f: \or: \int_incr:N \l__regex_balance_int @@ -2029,23 +2052,27 @@ \cs_new_protected:Npn \__regex_query_get: { \l__regex_current_char_int - = \etex_mutoglue:D \tex_muskip:D \l__regex_current_pos_int - \l__regex_current_catcode_int = \etex_gluestretch:D - \etex_mutoglue:D \tex_muskip:D \l__regex_current_pos_int + = \__intarray_item_fast:Nn \g__regex_charcode_intarray + { \l__regex_current_pos_int } \scan_stop: + \l__regex_current_catcode_int + = \__intarray_item_fast:Nn \g__regex_catcode_intarray + { \l__regex_current_pos_int } \scan_stop: } \cs_new_protected:Npn \__regex_use_state: { \trace:nnx { regex } { 2 } { state~\int_use:N \l__regex_current_state_int } - \tex_dimen:D \l__regex_current_state_int - = \l__regex_step_int sp \scan_stop: - \tex_the:D \tex_toks:D \l__regex_current_state_int - \tex_dimen:D \l__regex_current_state_int - = \__int_eval:w \l__regex_step_int + 1 \__int_eval_end: sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_state_active_intarray + { \l__regex_current_state_int } { \l__regex_step_int } + \__regex_toks_use:w \l__regex_current_state_int + \__intarray_gset_fast:Nnn \g__regex_state_active_intarray + { \l__regex_current_state_int } { \l__regex_step_int + 1 } } \cs_new_protected:Npn \__regex_use_state_and_submatches:nn #1 #2 { \int_set:Nn \l__regex_current_state_int {#1} - \if_int_compare:w \tex_dimen:D \l__regex_current_state_int + \if_int_compare:w + \__intarray_item_fast:Nn \g__regex_state_active_intarray + { \l__regex_current_state_int } < \l__regex_step_int \tl_set:Nn \l__regex_current_submatches_prop {#2} \exp_after:wN \__regex_use_state: @@ -2070,7 +2097,10 @@ \int_add:Nn \l__regex_current_state_int {#2} \exp_not:n { - \if_int_compare:w \tex_dimen:D \l__regex_current_state_int #1 + \if_int_compare:w + \__intarray_item_fast:Nn \g__regex_state_active_intarray + { \l__regex_current_state_int } + #1 \exp_after:wN \__regex_use_state: \fi: } @@ -2088,12 +2118,13 @@ \cs_new_protected:Npn \__regex_store_state:n #1 { \__regex_store_submatches: - \tex_skip:D \l__regex_max_active_int = #1 sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_thread_state_intarray + { \l__regex_max_active_int } {#1} \int_incr:N \l__regex_max_active_int } \cs_new_protected:Npn \__regex_store_submatches: { - \tex_toks:D \l__regex_max_active_int \exp_after:wN + \__regex_toks_set:No \l__regex_max_active_int { \l__regex_current_submatches_prop } } \cs_new_protected:Npn \__regex_disable_submatches: @@ -2120,14 +2151,16 @@ } } \int_new:N \l__regex_replacement_csnames_int +\tl_new:N \l__regex_replacement_category_tl +\seq_new:N \l__regex_replacement_category_seq \tl_new:N \l__regex_balance_tl \cs_new:Npn \__regex_replacement_balance_one_match:n #1 { - \__regex_submatch_balance:n {#1} } \cs_new:Npn \__regex_replacement_do_one_match:n #1 { \__regex_query_range:nn - { \etex_glueshrink:D \tex_skip:D #1 } - { \tex_skip:D #1 } + { \__intarray_item_fast:Nn \g__regex_submatch_prev_intarray {#1} } + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {#1} } } \cs_new:Npn \__regex_replacement_exp_not:N #1 { \exp_not:n {#1} } \cs_new:Npn \__regex_query_range:nn #1#2 @@ -2143,22 +2176,35 @@ \else: \exp_after:wN \__prg_break: \fi: - \tex_the:D \tex_toks:D #1 \exp_stop_f: + \__regex_toks_use:w #1 \exp_stop_f: \exp_after:wN \__regex_query_range_loop:ww \__int_value:w \__int_eval:w #1 + 1 ; #2 ; } \cs_new:Npn \__regex_query_submatch:n #1 { \__regex_query_range:nn - { \tex_skip:D \__int_eval:w #1 } - { \etex_gluestretch:D \tex_skip:D \__int_eval:w #1 } + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {#1} } + { \__intarray_item_fast:Nn \g__regex_submatch_end_intarray {#1} } } \cs_new_protected:Npn \__regex_submatch_balance:n #1 { - \etex_glueshrink:D \etex_mutoglue:D \etex_muexpr:D - \tex_muskip:D \etex_gluestretch:D \tex_skip:D #1 - - \tex_muskip:D \tex_skip:D #1 - \scan_stop: + \__int_eval:w + \int_compare:nNnTF + { \__intarray_item_fast:Nn \g__regex_submatch_end_intarray {#1} } = 0 + { 0 } + { + \__intarray_item_fast:Nn \g__regex_balance_intarray + { \__intarray_item_fast:Nn \g__regex_submatch_end_intarray {#1} } + } + - + \int_compare:nNnTF + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {#1} } = 0 + { 0 } + { + \__intarray_item_fast:Nn \g__regex_balance_intarray + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {#1} } + } + \__int_eval_end: } \cs_new_protected:Npn \__regex_replacement:n #1 { @@ -2169,10 +2215,14 @@ \__regex_escape_use:nnnn { \if_charcode:w \c_right_brace_str ##1 - \__regex_replacement_rbrace:N \else: \__tl_build_one:n \fi: ##1 + \__regex_replacement_rbrace:N + \else: + \__regex_replacement_normal:n + \fi: + ##1 } { \__regex_replacement_escaped:N ##1 } - { \__tl_build_one:n ##1 } + { \__regex_replacement_normal:n ##1 } {#1} \prg_do_nothing: \prg_do_nothing: \if_int_compare:w \l__regex_replacement_csnames_int > 0 \exp_stop_f: @@ -2181,6 +2231,12 @@ \__tl_build_one:x { \prg_replicate:nn \l__regex_replacement_csnames_int \cs_end: } \fi: + \seq_if_empty:NF \l__regex_replacement_category_seq + { + \__msg_kernel_error:nnx { regex } { replacement-missing-rparen } + { \seq_count:N \l__regex_replacement_category_seq } + \seq_clear:N \l__regex_replacement_category_seq + } \cs_gset:Npx \__regex_replacement_balance_one_match:n ##1 { + \int_use:N \l__regex_balance_int @@ -2196,11 +2252,27 @@ \cs_set:Npn \__regex_replacement_do_one_match:n ##1 { \__regex_query_range:nn - { \etex_glueshrink:D \tex_skip:D ##1 } - { \tex_skip:D ##1 } + { \__intarray_item_fast:Nn \g__regex_submatch_prev_intarray {##1} } + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {##1} } #1 } } +\cs_new_protected:Npn \__regex_replacement_normal:n #1 + { + \tl_if_empty:NTF \l__regex_replacement_category_tl + { \__tl_build_one:n {#1} } + { % ( + \token_if_eq_charcode:NNTF #1 ) + { + \seq_pop:NN \l__regex_replacement_category_seq + \l__regex_replacement_category_tl + } + { + \use:c { __regex_replacement_c_ \l__regex_replacement_category_tl :w } + \__regex_replacement_normal:n {#1} + } + } + } \cs_new_protected:Npn \__regex_replacement_escaped:N #1 { \cs_if_exist_use:cF { __regex_replacement_#1:w } @@ -2208,7 +2280,8 @@ \if_int_compare:w 1 < 1#1 \exp_stop_f: \__regex_replacement_put_submatch:n {#1} \else: - \__tl_build_one:o { \token_to_str:N #1 } + \exp_args:No \__regex_replacement_normal:n + { \token_to_str:N #1 } \fi: } } @@ -2224,28 +2297,26 @@ } \cs_new_protected:Npn \__regex_replacement_g:w #1#2 { - \str_if_eq_x:nnTF { #1#2 } { \__tl_build_one:n \c_left_brace_str } - { - \int_zero:N \l__regex_internal_a_int - \__regex_replacement_g_digits:NN - } + \str_if_eq_x:nnTF { #1#2 } { \__regex_replacement_normal:n \c_left_brace_str } + { \l__regex_internal_a_int = \__regex_replacement_g_digits:NN } { \__regex_replacement_error:NNN g #1 #2 } } -\cs_new_protected:Npn \__regex_replacement_g_digits:NN #1#2 +\cs_new:Npn \__regex_replacement_g_digits:NN #1#2 { - \token_if_eq_meaning:NNTF #1 \__tl_build_one:n + \token_if_eq_meaning:NNTF #1 \__regex_replacement_normal:n { \if_int_compare:w 1 < 1#2 \exp_stop_f: - \int_set:Nn \l__regex_internal_a_int - { 10 * \l__regex_internal_a_int + #2 } + #2 \exp_after:wN \use_i:nnn \exp_after:wN \__regex_replacement_g_digits:NN \else: + \exp_stop_f: \exp_after:wN \__regex_replacement_error:NNN \exp_after:wN g \fi: } { + \exp_stop_f: \if_meaning:w \__regex_replacement_rbrace:N #1 \exp_args:No \__regex_replacement_put_submatch:n { \int_use:N \l__regex_internal_a_int } @@ -2259,34 +2330,31 @@ } \cs_new_protected:Npn \__regex_replacement_c:w #1#2 { - \token_if_eq_meaning:NNTF #1 \__tl_build_one:n + \token_if_eq_meaning:NNTF #1 \__regex_replacement_normal:n { - \cs_if_exist_use:cF { __regex_replacement_c_#2:w } - { \__regex_replacement_error:NNN c #1#2 } + \exp_after:wN \token_if_eq_charcode:NNTF \c_left_brace_str #2 + { \__regex_replacement_cu_aux:Nw \__regex_replacement_exp_not:N } + { + \cs_if_exist:cTF { __regex_replacement_c_#2:w } + { \__regex_replacement_cat:NNN #2 } + { \__regex_replacement_error:NNN c #1#2 } + } } { \__regex_replacement_error:NNN c #1#2 } } -\cs_new_protected:cpn { __regex_replacement_c_ \c_left_brace_str :w } +\cs_new_protected:Npn \__regex_replacement_cu_aux:Nw #1 { \if_case:w \l__regex_replacement_csnames_int - \__tl_build_one:n - { \exp_not:n { \exp_after:wN \__regex_replacement_exp_not:N \cs:w } } + \__tl_build_one:n { \exp_not:n { \exp_after:wN #1 \cs:w } } \else: - \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:N \cs:w } } + \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:V \cs:w } } \fi: \int_incr:N \l__regex_replacement_csnames_int } \cs_new_protected:Npn \__regex_replacement_u:w #1#2 { - \str_if_eq_x:nnTF { #1#2 } { \__tl_build_one:n \c_left_brace_str } - { - \if_case:w \l__regex_replacement_csnames_int - \__tl_build_one:n { \exp_not:n { \exp_after:wN \exp_not:V \cs:w } } - \else: - \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:V \cs:w } } - \fi: - \int_incr:N \l__regex_replacement_csnames_int - } + \str_if_eq_x:nnTF { #1#2 } { \__regex_replacement_normal:n \c_left_brace_str } + { \__regex_replacement_cu_aux:Nw \exp_not:V } { \__regex_replacement_error:NNN u #1#2 } } \cs_new_protected:Npn \__regex_replacement_rbrace:N #1 @@ -2295,18 +2363,36 @@ \__tl_build_one:n \cs_end: \int_decr:N \l__regex_replacement_csnames_int \else: - \__tl_build_one:n #1 + \__regex_replacement_normal:n {#1} \fi: } +\cs_new_protected:Npn \__regex_replacement_cat:NNN #1#2#3 + { + \token_if_eq_meaning:NNTF \prg_do_nothing: #3 + { \__msg_kernel_error:nn { regex } { replacement-catcode-end } } + { + \int_compare:nNnTF { \l__regex_replacement_csnames_int } > 0 + { + \__msg_kernel_error:nnnn + { regex } { replacement-catcode-in-cs } {#1} {#3} + #2 #3 + } + { + \str_if_eq:nnTF { #2 #3 } { \__regex_replacement_normal:n ( } % ) + { + \seq_push:NV \l__regex_replacement_category_seq + \l__regex_replacement_category_tl + \tl_set:Nn \l__regex_replacement_category_tl {#1} + } + { \use:c { __regex_replacement_c_#1:w } #2 #3 } + } + } + } \group_begin: \cs_new_protected:Npn \__regex_replacement_char:nNN #1#2#3 { - \if_meaning:w \prg_do_nothing: #3 - \__msg_kernel_error:nn { regex } { replacement-catcode-end } - \else: - \tex_lccode:D 0 = `#3 \scan_stop: - \tex_lowercase:D { \__tl_build_one:n {#1} } - \fi: + \tex_lccode:D 0 = `#3 \scan_stop: + \tex_lowercase:D { \__tl_build_one:n {#1} } } \char_set_catcode_active:N \^^@ \cs_new_protected:Npn \__regex_replacement_c_A:w @@ -2351,15 +2437,11 @@ } \cs_new_protected:Npn \__regex_replacement_c_S:w #1#2 { - \if_meaning:w \prg_do_nothing: #2 - \__msg_kernel_error:nn { regex } { replacement-catcode-end } - \else: - \if_int_compare:w `#2 = 0 \exp_stop_f: - \__msg_kernel_error:nn { regex } { replacement-null-space } - \fi: - \tex_lccode:D `\ = `#2 \scan_stop: - \tex_lowercase:D { \__tl_build_one:n {~} } + \if_int_compare:w `#2 = 0 \exp_stop_f: + \__msg_kernel_error:nn { regex } { replacement-null-space } \fi: + \tex_lccode:D `\ = `#2 \scan_stop: + \tex_lowercase:D { \__tl_build_one:n {~} } } \char_set_catcode_alignment:N \^^@ \cs_new_protected:Npn \__regex_replacement_c_T:w @@ -2433,8 +2515,12 @@ \int_new:N \l__regex_match_count_int \flag_new:n { __regex_begin } \flag_new:n { __regex_end } +\int_new:N \l__regex_min_submatch_int \int_new:N \l__regex_submatch_int \int_new:N \l__regex_zeroth_submatch_int +\__intarray_new:Nn \g__regex_submatch_prev_intarray { 65536 } +\__intarray_new:Nn \g__regex_submatch_begin_intarray { 65536 } +\__intarray_new:Nn \g__regex_submatch_end_intarray { 65536 } \cs_new_protected:Npn \__regex_return: { \if_meaning:w \c_true_bool \g__regex_success_bool @@ -2488,15 +2574,29 @@ { \if_int_compare:w \l__regex_start_pos_int < \l__regex_success_pos_int \__regex_extract: - \tex_skip:D \l__regex_zeroth_submatch_int - = \l__regex_start_pos_int sp - plus \tex_skip:D \l__regex_zeroth_submatch_int \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_submatch_prev_intarray + { \l__regex_zeroth_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g__regex_submatch_end_intarray + { \l__regex_zeroth_submatch_int } + { + \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray + { \l__regex_zeroth_submatch_int } + } + \__intarray_gset_fast:Nnn \g__regex_submatch_begin_intarray + { \l__regex_zeroth_submatch_int } + { \l__regex_start_pos_int } \fi: } #1 \__regex_match:n {#2} - \tex_skip:D \l__regex_submatch_int - = \l__regex_start_pos_int sp plus \l__regex_max_pos_int sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_submatch_prev_intarray + { \l__regex_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g__regex_submatch_end_intarray + { \l__regex_submatch_int } + { \l__regex_max_pos_int } + \__intarray_gset_fast:Nnn \g__regex_submatch_begin_intarray + { \l__regex_submatch_int } + { \l__regex_start_pos_int } \int_incr:N \l__regex_submatch_int \if_meaning:w \c_true_bool \l__regex_empty_success_bool \if_int_compare:w \l__regex_start_pos_int = \l__regex_max_pos_int @@ -2514,7 +2614,7 @@ { \s__seq \int_step_function:nnnN - { 2 * \l__regex_max_state_int } + { \l__regex_min_submatch_int } { 1 } { \l__regex_submatch_int - 1 } \__regex_extract_seq_aux:n @@ -2560,7 +2660,12 @@ \int_set_eq:NN \l__regex_zeroth_submatch_int \l__regex_submatch_int \prg_replicate:nn \l__regex_capturing_group_int { - \tex_skip:D \l__regex_submatch_int 0 sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_submatch_begin_intarray + { \l__regex_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g__regex_submatch_end_intarray + { \l__regex_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g__regex_submatch_prev_intarray + { \l__regex_submatch_int } { 0 } \int_incr:N \l__regex_submatch_int } \prop_map_inline:Nn \l__regex_success_submatches_prop @@ -2572,21 +2677,14 @@ \fi: \__int_eval:w \l__regex_zeroth_submatch_int + ##1 {##2} } - \tex_skip:D \l__regex_zeroth_submatch_int - = \tex_the:D \tex_skip:D \l__regex_zeroth_submatch_int - minus \l__regex_start_pos_int sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_submatch_prev_intarray + { \l__regex_zeroth_submatch_int } { \l__regex_start_pos_int } \fi: } \cs_new_protected:Npn \__regex_extract_b:wn #1 < #2 - { - \tex_skip:D #1 = #2 sp - plus \etex_gluestretch:D \tex_skip:D #1 \scan_stop: - } + { \__intarray_gset_fast:Nnn \g__regex_submatch_begin_intarray {#1} {#2} } \cs_new_protected:Npn \__regex_extract_e:wn #1 > #2 - { - \tex_skip:D #1 - = 1 \tex_skip:D #1 plus #2 sp \scan_stop: - } + { \__intarray_gset_fast:Nnn \g__regex_submatch_end_intarray {#1} {#2} } \cs_new_protected:Npn \__regex_replace_once:nnN #1#2#3 { \group_begin: @@ -2607,7 +2705,10 @@ { \__regex_replacement_do_one_match:n { \l__regex_zeroth_submatch_int } \__regex_query_range:nn - { \etex_gluestretch:D \tex_skip:D \l__regex_zeroth_submatch_int } + { + \__intarray_item_fast:Nn \g__regex_submatch_end_intarray + { \l__regex_zeroth_submatch_int } + } { \l__regex_max_pos_int } } \__regex_group_end_replace:N #3 @@ -2624,7 +2725,7 @@ { 0 \int_step_function:nnnN - { 2 * \l__regex_max_state_int } + { \l__regex_min_submatch_int } \l__regex_capturing_group_int { \l__regex_submatch_int - 1 } \__regex_replacement_balance_one_match:n @@ -2632,7 +2733,7 @@ \tl_set:Nx \l__regex_internal_a_tl { \int_step_function:nnnN - { 2 * \l__regex_max_state_int } + { \l__regex_min_submatch_int } \l__regex_capturing_group_int { \l__regex_submatch_int - 1 } \__regex_replacement_do_one_match:n @@ -2668,38 +2769,38 @@ } } \__msg_kernel_new:nnnn { regex } { trailing-backslash } - { Trailing~escape~character~`\iow_char:N\\'. } + { Trailing~escape~character~'\iow_char:N\\'. } { A~regular~expression~or~its~replacement~text~ends~with~ - the~escape~character~`\iow_char:N\\'.~It~will~be~ignored. + the~escape~character~'\iow_char:N\\'.~It~will~be~ignored. } \__msg_kernel_new:nnnn { regex } { x-missing-rbrace } - { Missing~closing~brace~in~`\iow_char:N\\x'~hexadecimal~sequence. } + { Missing~closing~brace~in~'\iow_char:N\\x'~hexadecimal~sequence. } { You~wrote~something~like~ - `\iow_char:N\\x\{...#1'.~ + '\iow_char:N\\x\{...#1'.~ The~closing~brace~is~missing. } \__msg_kernel_new:nnnn { regex } { x-overflow } - { Character~code~`#1'~too~large~in~`\iow_char:N\\x'~hexadecimal~sequence. } + { Character~code~'#1'~too~large~in~'\iow_char:N\\x'~hexadecimal~sequence. } { You~wrote~something~like~ - `\iow_char:N\\x\{\int_to_Hex:n{#1}\}'.~ + '\iow_char:N\\x\{\int_to_Hex:n{#1}\}'.~ The~character~code~#1~is~larger~than~ the~maximum~value~\int_use:N \c_max_char_int. } \__msg_kernel_new:nnnn { regex } { invalid-quantifier } - { Braced~quantifier~`#1'~may~not~be~followed~by~`#2'. } + { Braced~quantifier~'#1'~may~not~be~followed~by~'#2'. } { - The~character~`#2'~is~invalid~in~the~braced~quantifier~`#1'.~ - The~only~valid~quantifiers~are~`*',~`?',~`+',~`{<int>}',~ - `{<min>,}'~and~`{<min>,<max>}',~optionally~followed~by~`?'. + The~character~'#2'~is~invalid~in~the~braced~quantifier~'#1'.~ + The~only~valid~quantifiers~are~'*',~'?',~'+',~'{<int>}',~ + '{<min>,}'~and~'{<min>,<max>}',~optionally~followed~by~'?'. } \__msg_kernel_new:nnnn { regex } { missing-rbrack } { Missing~right~bracket~inserted~in~regular~expression. } { LaTeX~was~given~a~regular~expression~where~a~character~class~ - was~started~with~`[',~but~the~matching~`]'~is~missing. + was~started~with~'[',~but~the~matching~']'~is~missing. } \__msg_kernel_new:nnnn { regex } { missing-rparen } { @@ -2719,7 +2820,7 @@ } \__msg_kernel_new:nnnn { regex } { bad-escape } { - Invalid~escape~`\iow_char:N\\#1'~ + Invalid~escape~'\iow_char:N\\#1'~ \__regex_if_in_cs:TF { within~a~control~sequence. } { \__regex_if_in_class:TF @@ -2728,102 +2829,102 @@ } } { - The~escape~sequence~`\iow_char:N\\#1'~may~not~appear~ + The~escape~sequence~'\iow_char:N\\#1'~may~not~appear~ \__regex_if_in_cs:TF { within~a~control~sequence~test~introduced~by~ - `\iow_char:N\\c\iow_char:N\{'. + '\iow_char:N\\c\iow_char:N\{'. } { \__regex_if_in_class:TF { within~a~character~class~ } - { following~a~category~test~such~as~`\iow_char:N\\cL'~ } + { following~a~category~test~such~as~'\iow_char:N\\cL'~ } because~it~does~not~match~exactly~one~character. } } \__msg_kernel_new:nnnn { regex } { range-missing-end } - { Invalid~end-point~for~range~`#1-#2'~in~character~class. } + { Invalid~end-point~for~range~'#1-#2'~in~character~class. } { - The~end-point~`#2'~of~the~range~`#1-#2'~may~not~serve~as~an~ + The~end-point~'#2'~of~the~range~'#1-#2'~may~not~serve~as~an~ end-point~for~a~range:~alphanumeric~characters~should~not~be~ escaped,~and~non-alphanumeric~characters~should~be~escaped. } \__msg_kernel_new:nnnn { regex } { range-backwards } - { Range~`[#1-#2]'~out~of~order~in~character~class. } + { Range~'[#1-#2]'~out~of~order~in~character~class. } { - In~ranges~of~characters~`[x-y]'~appearing~in~character~classes,~ + In~ranges~of~characters~'[x-y]'~appearing~in~character~classes,~ the~first~character~code~must~not~be~larger~than~the~second.~ - Here,~`#1'~has~character~code~\int_eval:n {`#1},~while~ - `#2'~has~character~code~\int_eval:n {`#2}. + Here,~'#1'~has~character~code~\int_eval:n {`#1},~while~ + '#2'~has~character~code~\int_eval:n {`#2}. } \__msg_kernel_new:nnnn { regex } { c-bad-mode } - { Invalid~nested~`\iow_char:N\\c'~escape~in~regular~expression. } + { Invalid~nested~'\iow_char:N\\c'~escape~in~regular~expression. } { - The~`\iow_char:N\\c'~escape~cannot~be~used~within~ - a~control~sequence~test~`\iow_char:N\\c{...}'.~ - To~combine~several~category~tests,~use~`\iow_char:N\\c[...]'. + The~'\iow_char:N\\c'~escape~cannot~be~used~within~ + a~control~sequence~test~'\iow_char:N\\c{...}'.~ + To~combine~several~category~tests,~use~'\iow_char:N\\c[...]'. } \__msg_kernel_new:nnnn { regex } { c-missing-rbrace } - { Missing~right~brace~inserted~for~`\iow_char:N\\c'~escape. } + { Missing~right~brace~inserted~for~'\iow_char:N\\c'~escape. } { LaTeX~was~given~a~regular~expression~where~a~ - `\iow_char:N\\c\iow_char:N\{...'~construction~was~not~ended~ - with~a~closing~brace~`\iow_char:N\}'. + '\iow_char:N\\c\iow_char:N\{...'~construction~was~not~ended~ + with~a~closing~brace~'\iow_char:N\}'. } \__msg_kernel_new:nnnn { regex } { c-missing-rbrack } - { Missing~right~bracket~inserted~for~`\iow_char:N\\c'~escape. } + { Missing~right~bracket~inserted~for~'\iow_char:N\\c'~escape. } { - A~construction~`\iow_char:N\\c[...'~appears~in~a~ - regular~expression,~but~the~closing~`]'~is~not~present. + A~construction~'\iow_char:N\\c[...'~appears~in~a~ + regular~expression,~but~the~closing~']'~is~not~present. } \__msg_kernel_new:nnnn { regex } { c-missing-category } - { Invalid~character~`#1'~following~`\iow_char:N\\c'~escape. } + { Invalid~character~'#1'~following~'\iow_char:N\\c'~escape. } { - In~regular~expressions,~the~`\iow_char:N\\c'~escape~sequence~ + In~regular~expressions,~the~'\iow_char:N\\c'~escape~sequence~ may~only~be~followed~by~a~left~brace,~a~left~bracket,~or~a~ capital~letter~representing~a~character~category,~namely~ - one~of~`ABCDELMOPSTU'. + one~of~'ABCDELMOPSTU'. } \__msg_kernel_new:nnnn { regex } { c-trailing } - { Trailing~category~code~escape~`\iow_char:N\\c'... } + { Trailing~category~code~escape~'\iow_char:N\\c'... } { - A~regular~expression~ends~with~`\iow_char:N\\c'~followed~ + A~regular~expression~ends~with~'\iow_char:N\\c'~followed~ by~a~letter.~It~will~be~ignored. } \__msg_kernel_new:nnnn { regex } { u-missing-lbrace } - { Missing~left~brace~following~`\iow_char:N\\u'~escape. } + { Missing~left~brace~following~'\iow_char:N\\u'~escape. } { - The~`\iow_char:N\\u'~escape~sequence~must~be~followed~by~ + The~'\iow_char:N\\u'~escape~sequence~must~be~followed~by~ a~brace~group~with~the~name~of~the~variable~to~use. } \__msg_kernel_new:nnnn { regex } { u-missing-rbrace } - { Missing~right~brace~inserted~for~`\iow_char:N\\u'~escape. } + { Missing~right~brace~inserted~for~'\iow_char:N\\u'~escape. } { LaTeX~ \str_if_eq_x:nnTF { } {#2} { reached~the~end~of~the~string~ } - { encountered~an~escaped~alphanumeric~character `\iow_char:N\\#2'~ } - when~parsing~the~argument~of~an~`\iow_char:N\\u\iow_char:N\{...\}'~escape. + { encountered~an~escaped~alphanumeric~character '\iow_char:N\\#2'~ } + when~parsing~the~argument~of~an~'\iow_char:N\\u\iow_char:N\{...\}'~escape. } \__msg_kernel_new:nnnn { regex } { posix-unsupported } - { POSIX~collating~element~`[#1 ~ #1]'~not~supported. } + { POSIX~collating~element~'[#1 ~ #1]'~not~supported. } { - The~`[.foo.]'~and~`[=bar=]'~syntaxes~have~a~special~meaning~ + The~'[.foo.]'~and~'[=bar=]'~syntaxes~have~a~special~meaning~ in~POSIX~regular~expressions.~This~is~not~supported~by~LaTeX.~ Maybe~you~forgot~to~escape~a~left~bracket~in~a~character~class? } \__msg_kernel_new:nnnn { regex } { posix-unknown } - { POSIX~class~`[:#1:]'~unknown. } + { POSIX~class~'[:#1:]'~unknown. } { - `[:#1:]'~is~not~among~the~known~POSIX~classes~ - `[:alnum:]',~`[:alpha:]',~`[:ascii:]',~`[:blank:]',~ - `[:cntrl:]',~`[:digit:]',~`[:graph:]',~`[:lower:]',~ - `[:print:]',~`[:punct:]',~`[:space:]',~`[:upper:]',~ - `[:word:]',~and~`[:xdigit:]'. + '[:#1:]'~is~not~among~the~known~POSIX~classes~ + '[:alnum:]',~'[:alpha:]',~'[:ascii:]',~'[:blank:]',~ + '[:cntrl:]',~'[:digit:]',~'[:graph:]',~'[:lower:]',~ + '[:print:]',~'[:punct:]',~'[:space:]',~'[:upper:]',~ + '[:word:]',~and~'[:xdigit:]'. } \__msg_kernel_new:nnnn { regex } { posix-missing-close } - { Missing~closing~`:]'~for~POSIX~class. } - { The~POSIX~syntax~`#1'~must~be~followed~by~`:]',~not~`#2'. } + { Missing~closing~':]'~for~POSIX~class. } + { The~POSIX~syntax~'#1'~must~be~followed~by~':]',~not~'#2'. } \__msg_kernel_new:nnnn { regex } { result-unbalanced } { Missing~brace~inserted~when~#1. } { @@ -2833,58 +2934,68 @@ #2~left,~#3~right. } \__msg_kernel_new:nnnn { regex } { unknown-option } - { Unknown~option~`#1'~for~regular~expressions. } + { Unknown~option~'#1'~for~regular~expressions. } { - The~only~available~option~is~`case-insensitive',~toggled~by~ - `(?i)'~and~`(?-i)'. + The~only~available~option~is~'case-insensitive',~toggled~by~ + '(?i)'~and~'(?-i)'. } \__msg_kernel_new:nnnn { regex } { special-group-unknown } - { Unknown~special~group~`#1~...'~in~a~regular~expression. } + { Unknown~special~group~'#1~...'~in~a~regular~expression. } { - The~only~valid~constructions~starting~with~`(?'~are~ - `(?:~...~)',~`(?|~...~)',~`(?i)',~and~`(?-i)'. + The~only~valid~constructions~starting~with~'(?'~are~ + '(?:~...~)',~'(?|~...~)',~'(?i)',~and~'(?-i)'. } \__msg_kernel_new:nnnn { regex } { replacement-c } - { Misused~`\iow_char:N\\c'~command~in~a~replacement~text. } + { Misused~'\iow_char:N\\c'~command~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\c'~escape~sequence~ - can~be~followed~by~one~of~the~letters~`ABCDELMOPSTU'~ - or~a~brace~group,~not~by~`#1'. + In~a~replacement~text,~the~'\iow_char:N\\c'~escape~sequence~ + can~be~followed~by~one~of~the~letters~'ABCDELMOPSTU'~ + or~a~brace~group,~not~by~'#1'. } \__msg_kernel_new:nnnn { regex } { replacement-u } - { Misused~`\iow_char:N\\u'~command~in~a~replacement~text. } + { Misused~'\iow_char:N\\u'~command~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\u'~escape~sequence~ + In~a~replacement~text,~the~'\iow_char:N\\u'~escape~sequence~ must~be~~followed~by~a~brace~group~holding~the~name~of~the~ variable~to~use. } \__msg_kernel_new:nnnn { regex } { replacement-g } { - Missing~brace~for~the~`\iow_char:N\\g'~construction~ + Missing~brace~for~the~'\iow_char:N\\g'~construction~ in~a~replacement~text. } { In~the~replacement~text~for~a~regular~expression~search,~ - submatches~are~represented~either~as~`\iow_char:N \\g{dd..d}',~ - or~`\\d',~where~`d'~are~single~digits.~Here,~a~brace~is~missing. + submatches~are~represented~either~as~'\iow_char:N \\g{dd..d}',~ + or~'\\d',~where~'d'~are~single~digits.~Here,~a~brace~is~missing. } \__msg_kernel_new:nnnn { regex } { replacement-catcode-end } { - Missing~character~for~the~`\iow_char:N\\c<category><character>'~ + Missing~character~for~the~'\iow_char:N\\c<category><character>'~ construction~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\c'~escape~sequence~ - can~be~followed~by~one~of~the~letters~`ABCDELMOPSTU'~representing~ + In~a~replacement~text,~the~'\iow_char:N\\c'~escape~sequence~ + can~be~followed~by~one~of~the~letters~'ABCDELMOPSTU'~representing~ the~character~category.~Then,~a~character~must~follow.~LaTeX~ reached~the~end~of~the~replacement~when~looking~for~that. } +\__msg_kernel_new:nnnn { regex } { replacement-catcode-in-cs } + { + Category~code~'\iow_char:N\\c#1#3'~ignored~inside~ + '\iow_char:N\\c\{...\}'~in~a~replacement~text. + } + { + In~a~replacement~text,~the~category~codes~of~the~argument~of~ + '\iow_char:N\\c\{...\}'~are~ignored~when~building~the~control~ + sequence~name. + } \__msg_kernel_new:nnnn { regex } { replacement-null-space } { TeX~cannot~build~a~space~token~with~character~code~0. } { You~asked~for~a~character~token~with~category~space,~ and~character~code~0,~for~instance~through~ - `\iow_char:N\\cS\iow_char:N\\x00'.~ + '\iow_char:N\\cS\iow_char:N\\x00'.~ This~specific~case~is~impossible~and~will~be~replaced~ by~a~normal~space. } @@ -2894,6 +3005,12 @@ There~ \int_compare:nTF { #1 = 1 } { was } { were } ~ #1~ missing~right~\int_compare:nTF { #1 = 1 } { brace } { braces } . } +\__msg_kernel_new:nnnn { regex } { replacement-missing-rparen } + { Missing~right~parenthesis~inserted~in~replacement~text. } + { + There~ \int_compare:nTF { #1 = 1 } { was } { were } ~ #1~ + missing~right~\int_compare:nTF { #1 = 1 } { parenthesis } { parentheses } . + } \cs_new:Npn \__regex_msg_repeated:nnN #1#2#3 { \str_if_eq_x:nnF { #1 #2 } { 1 0 } @@ -2918,7 +3035,7 @@ { \l__regex_max_state_int - 1 } { \trace:nnx { regex } { #1 } - { \iow_char:N \\toks ##1 = { \tex_the:D \tex_toks:D ##1 } } + { \iow_char:N \\toks ##1 = { \__regex_toks_use:w ##1 } } } } %% diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty index 671cb91fc11..b3ce165d5e8 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3regex.sty @@ -6,7 +6,7 @@ %% %% l3regex.dtx (with options: `package') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of @@ -19,8 +19,8 @@ %% and all files in that bundle must be distributed together. %% %% File: l3regex.dtx Copyright (C) 2011-2017 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{l3regex}{Support package l3kernel too old} @@ -32,10 +32,46 @@ }% \endinput } -\ProvidesExplPackage{l3regex}{2017/04/01}{} +\ProvidesExplPackage{l3regex}{2017/05/13}{} {L3 Experimental regular expressions} -\RequirePackage{l3tl-build, l3tl-analysis, l3str-convert} +\RequirePackage{l3tl-build, l3tl-analysis, l3intarray} \cs_generate_variant:Nn \tl_to_str:n { V } +\cs_new_protected:Npn \__regex_standard_escapechar: + { \int_set:Nn \tex_escapechar:D { `\\ } } +\cs_new:Npn \__regex_toks_use:w { \tex_the:D \tex_toks:D } +\cs_new_protected:Npn \__regex_toks_clear:N #1 + { \tex_toks:D #1 { } } +\cs_new_eq:NN \__regex_toks_set:Nn \tex_toks:D +\cs_new_protected:Npn \__regex_toks_set:No #1 + { \__regex_toks_set:Nn #1 \exp_after:wN } +\cs_new_protected:Npn \__regex_toks_memcpy:NNn #1#2#3 + { + \prg_replicate:nn {#3} + { + \tex_toks:D #1 = \tex_toks:D #2 + \int_incr:N #1 + \int_incr:N #2 + } + } +\cs_new_protected:Npn \__regex_toks_put_left:Nx #1#2 + { + \cs_set:Npx \__regex_tmp:w { #2 } + \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN + { \exp_after:wN \__regex_tmp:w \tex_the:D \tex_toks:D #1 } + } +\cs_new_protected:Npn \__regex_toks_put_right:Nx #1#2 + { + \cs_set:Npx \__regex_tmp:w {#2} + \tex_toks:D #1 \exp_after:wN + { \tex_the:D \tex_toks:D \exp_after:wN #1 \__regex_tmp:w } + } +\cs_new_protected:Npn \__regex_toks_put_right:Nn #1#2 + { \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D #1 #2 } } +\cs_new:Npn \__regex_current_cs_to_str: + { + \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N + \tex_the:D \tex_toks:D \l__regex_current_pos_int + } \cs_new:Npn \__regex_tmp:w { } \tl_new:N \l__regex_internal_a_tl \tl_new:N \l__regex_internal_b_tl @@ -50,8 +86,15 @@ \__regex_branch:n { \__regex_class:NnnnN \c_true_bool { } { 1 } { 0 } \c_true_bool } } +\__intarray_new:Nn \g__regex_charcode_intarray { 65536 } +\__intarray_new:Nn \g__regex_catcode_intarray { 65536 } +\__intarray_new:Nn \g__regex_balance_intarray { 65536 } \int_new:N \l__regex_balance_int \tl_new:N \l__regex_cs_name_tl +\int_const:Nn \c__regex_ascii_min_int { 0 } +\int_const:Nn \c__regex_ascii_max_control_int { 31 } +\int_const:Nn \c__regex_ascii_max_int { 127 } +\int_const:Nn \c__regex_ascii_lower_int { `a - `A } \cs_new_protected:Npn \__regex_break_true:w #1 \__regex_break_point:TF #2 #3 {#2} \cs_new_protected:Npn \__regex_break_point:TF #1 #2 { #2 } @@ -108,12 +151,12 @@ \if_int_compare:w \l__regex_current_char_int > `Z \exp_stop_f: \if_int_compare:w \l__regex_current_char_int > `z \exp_stop_f: \else: \if_int_compare:w \l__regex_current_char_int < `a \exp_stop_f: \else: - \int_sub:Nn \l__regex_case_changed_char_int { \c__str_ascii_lower_int } + \int_sub:Nn \l__regex_case_changed_char_int { \c__regex_ascii_lower_int } \fi: \fi: \else: \if_int_compare:w \l__regex_current_char_int < `A \exp_stop_f: \else: - \int_add:Nn \l__regex_case_changed_char_int { \c__str_ascii_lower_int } + \int_add:Nn \l__regex_case_changed_char_int { \c__regex_ascii_lower_int } \fi: \fi: } @@ -152,12 +195,7 @@ \int_compare:nNnTF \l__regex_current_catcode_int = 0 { \tl_set:Nx \l__regex_internal_a_tl - { - \scan_stop: - \exp_after:wN \exp_after:wN \exp_after:wN \cs_to_str:N - \tex_the:D \tex_toks:D \l__regex_current_pos_int - \scan_stop: - } + { \scan_stop: \__regex_current_cs_to_str: \scan_stop: } \tl_if_in:noTF { \scan_stop: #1 \scan_stop: } \l__regex_internal_a_tl { \__regex_break_true:w } { } } @@ -168,12 +206,7 @@ \int_compare:nNnT \l__regex_current_catcode_int = 0 { \group_begin: - \tl_set:Nx \l__regex_cs_name_tl - { - \exp_after:wN \exp_after:wN - \exp_after:wN \cs_to_str:N - \tex_the:D \tex_toks:D \l__regex_current_pos_int - } + \tl_set:Nx \l__regex_cs_name_tl { \__regex_current_cs_to_str: } \__regex_single_match: \__regex_disable_submatches: \__regex_build_for_cs:n {#1} @@ -222,16 +255,16 @@ \cs_new_protected:Npn \__regex_posix_ascii: { \__regex_item_caseful_range:nn - \c__str_ascii_min_int - \c__str_ascii_max_int + \c__regex_ascii_min_int + \c__regex_ascii_max_int } \cs_new_eq:NN \__regex_posix_blank: \__regex_prop_h: \cs_new_protected:Npn \__regex_posix_cntrl: { \__regex_item_caseful_range:nn - \c__str_ascii_min_int - \c__str_ascii_max_control_int - \__regex_item_caseful_equal:n \c__str_ascii_max_int + \c__regex_ascii_min_int + \c__regex_ascii_max_control_int + \__regex_item_caseful_equal:n \c__regex_ascii_max_int } \cs_new_eq:NN \__regex_posix_digit: \__regex_prop_d: \cs_new_protected:Npn \__regex_posix_graph: @@ -267,8 +300,8 @@ \cs_set:Npn \__regex_escape_unescaped:N ##1 { #1 } \cs_set:Npn \__regex_escape_escaped:N ##1 { #2 } \cs_set:Npn \__regex_escape_raw:N ##1 { #3 } - \int_set:Nn \tex_escapechar:D { `\\ } - \__str_gset_other:Nn \g__regex_internal_tl { #4 } + \__regex_standard_escapechar: + \tl_gset:Nx \g__regex_internal_tl { \__str_to_other_fast:n {#4} } \tl_set:Nx \l__regex_internal_b_tl { \exp_after:wN \__regex_escape_loop:N \g__regex_internal_tl @@ -321,36 +354,19 @@ } \cs_new:Npn \__regex_escape_x_end:w #1 ; { - \int_compare:nNnTF {#1} > \c__str_max_byte_int - { \__regex_escape_x_large:n {#1} } + \int_compare:nNnTF {#1} > \c_max_char_int + { + \if_false: { \fi: } + \__tl_build_one:o \l__regex_internal_b_tl + \__msg_kernel_error:nnx { regex } { x-overflow } {#1} + \tl_set:Nx \l__regex_internal_b_tl + { \if_false: } \fi: + } { \exp_last_unbraced:Nf \__regex_escape_raw:N - { \__str_output_byte:n {#1} } + { \char_generate:nn {#1} { 12 } } } } -\group_begin: - \char_set_catcode_other:n { 0 } - \cs_new:Npn \__regex_escape_x_large:n #1 - { - \if_false: { \fi: } - \__tl_build_one:o \l__regex_internal_b_tl - \int_compare:nNnTF {#1} > \c_max_char_int - { - \__msg_kernel_error:nnx { regex } { x-overflow } {#1} - \tl_set:Nx \l__regex_internal_b_tl - { \if_false: } \fi: - } - { - \char_set_lccode:nn { 0 } {#1} - \tex_lowercase:D - { - \tl_set:Nx \l__regex_internal_b_tl - { \if_false: } \fi: - \__regex_escape_raw:N ^^@ - } - } - } -\group_end: \cs_new:Npn \__regex_escape_x_test:N #1 { \str_if_eq_x:nnTF {#1} { break } { ; } @@ -368,7 +384,7 @@ \if_charcode:w \c_left_brace_str #1 \exp_after:wN \__regex_escape_x_loop:N \else: - \__str_hexadecimal_use:NTF #1 + \__regex_hexadecimal_use:NTF #1 { \exp_after:wN \__regex_escape_x:N } { ; \exp_after:wN \__regex_escape_loop:N \exp_after:wN #1 } \fi: @@ -377,7 +393,7 @@ { \str_if_eq_x:nnTF {#1} { break } { ; } { - \__str_hexadecimal_use:NTF #1 + \__regex_hexadecimal_use:NTF #1 { ; \__regex_escape_loop:N } { ; \__regex_escape_loop:N #1 } } @@ -387,7 +403,7 @@ \str_if_eq_x:nnTF {#1} { break } { ; \__regex_escape_x_loop_error:n { } {#1} } { - \__str_hexadecimal_use:NTF #1 + \__regex_hexadecimal_use:NTF #1 { \__regex_escape_x_loop:N } { \token_if_eq_charcode:NNTF \c_space_token #1 @@ -410,11 +426,32 @@ \tl_set:Nx \l__regex_internal_b_tl { \if_false: } \fi: \__regex_escape_loop:N #1 } +\prg_new_conditional:Npnn \__regex_hexadecimal_use:N #1 { TF } + { + \if_int_compare:w 1 < "1 \token_to_str:N #1 \exp_stop_f: + #1 \prg_return_true: + \else: + \if_case:w \__int_eval:w + \exp_after:wN ` \token_to_str:N #1 - `a + \__int_eval_end: + A + \or: B + \or: C + \or: D + \or: E + \or: F + \else: + \prg_return_false: + \exp_after:wN \use_none:n + \fi: + \prg_return_true: + \fi: + } \prg_new_conditional:Npnn \__regex_char_if_special:N #1 { TF } { \if_int_compare:w `#1 > `Z \exp_stop_f: \if_int_compare:w `#1 > `z \exp_stop_f: - \if_int_compare:w `#1 < \c__str_ascii_max_int + \if_int_compare:w `#1 < \c__regex_ascii_max_int \prg_return_true: \else: \prg_return_false: \fi: \else: \if_int_compare:w `#1 < `a \exp_stop_f: @@ -605,7 +642,7 @@ \cs_new_protected:Npn \__regex_compile:n #1 { \__regex_compile:w - \int_set:Nn \tex_escapechar:D { `\\ } + \__regex_standard_escapechar: \int_set_eq:NN \l__regex_mode_int \c__regex_outer_mode_int \__regex_escape_use:nnnn { @@ -1199,7 +1236,7 @@ { \if_int_odd:w \__int_eval:w \l__regex_catcodes_int / #1 \__int_eval_end: \else: - \tex_advance:D \l__regex_catcodes_int #1 + \int_add:Nn \l__regex_catcodes_int {#1} \fi: } \cs_new_protected:Npn \__regex_compile_c_lbrack_end: @@ -1327,8 +1364,8 @@ } \cs_new_protected:Npn \__regex_compile_u_in_cs: { - \exp_args:NNo \__str_gset_other:Nn \g__regex_internal_tl - { \l__regex_internal_a_tl } + \tl_gset:Nx \g__regex_internal_tl + { \exp_args:No \__str_to_other_fast:n { \l__regex_internal_a_tl } } \__tl_build_one:x { \tl_map_function:NN \g__regex_internal_tl @@ -1520,6 +1557,7 @@ { control~sequence~ \seq_use:Nn \l__regex_internal_seq { ~or~ } } } \int_new:N \l__regex_min_state_int +\int_set:Nn \l__regex_min_state_int { 1 } \int_new:N \l__regex_max_state_int \int_new:N \l__regex_left_state_int \int_new:N \l__regex_right_state_int @@ -1533,7 +1571,7 @@ } \cs_new_protected:Npn \__regex_build:N #1 { - \int_set:Nn \tex_escapechar:D { `\\ } + \__regex_standard_escapechar: \int_zero:N \l__regex_capturing_group_int \int_set_eq:NN \l__regex_max_state_int \l__regex_min_state_int \__regex_build_new_state: @@ -1573,27 +1611,13 @@ \seq_pop:NN \l__regex_right_state_seq \l__regex_internal_a_tl \int_set:Nn \l__regex_right_state_int \l__regex_internal_a_tl } -\cs_new_protected:Npn \__regex_toks_put_left:Nx #1#2 - { - \cs_set:Npx \__regex_tmp:w { #2 } - \tex_toks:D #1 \exp_after:wN \exp_after:wN \exp_after:wN - { \exp_after:wN \__regex_tmp:w \tex_the:D \tex_toks:D #1 } - } -\cs_new_protected:Npn \__regex_toks_put_right:Nx #1#2 - { - \cs_set:Npx \__regex_tmp:w {#2} - \tex_toks:D #1 \exp_after:wN - { \tex_the:D \tex_toks:D \exp_after:wN #1 \__regex_tmp:w } - } -\cs_new_protected:Npn \__regex_toks_put_right:Nn #1#2 - { \tex_toks:D #1 \exp_after:wN { \tex_the:D \tex_toks:D #1 #2 } } \cs_new_protected:Npn \__regex_build_transition_left:NNN #1#2#3 { \__regex_toks_put_left:Nx #2 { #1 { \int_eval:n { #3 - #2 } } } } \cs_new_protected:Npn \__regex_build_transition_right:nNn #1#2#3 { \__regex_toks_put_right:Nx #2 { #1 { \int_eval:n { #3 - #2 } } } } \cs_new_protected:Npn \__regex_build_new_state: { - \tex_toks:D \l__regex_max_state_int { } + \__regex_toks_clear:N \l__regex_max_state_int \int_set_eq:NN \l__regex_left_state_int \l__regex_right_state_int \int_set_eq:NN \l__regex_right_state_int \l__regex_max_state_int \int_incr:N \l__regex_max_state_int @@ -1756,15 +1780,12 @@ ( #1 - 1 ) * ( \l__regex_internal_b_int - \l__regex_internal_a_int ) } - \tex_advance:D \l__regex_right_state_int \l__regex_internal_c_int - \tex_advance:D \l__regex_max_state_int \l__regex_internal_c_int - \prg_replicate:nn \l__regex_internal_c_int - { - \tex_toks:D \l__regex_internal_b_int - = \tex_toks:D \l__regex_internal_a_int - \int_incr:N \l__regex_internal_a_int - \int_incr:N \l__regex_internal_b_int - } + \int_add:Nn \l__regex_right_state_int { \l__regex_internal_c_int } + \int_add:Nn \l__regex_max_state_int { \l__regex_internal_c_int } + \__regex_toks_memcpy:NNn + \l__regex_internal_b_int + \l__regex_internal_a_int + \l__regex_internal_c_int \fi: } \cs_new_protected:Npn \__regex_group_repeat:nnN #1#2#3 @@ -1892,6 +1913,8 @@ \int_new:N \l__regex_step_int \int_new:N \l__regex_min_active_int \int_new:N \l__regex_max_active_int +\__intarray_new:Nn \g__regex_state_active_intarray { 65536 } +\__intarray_new:Nn \g__regex_thread_state_intarray { 65536 } \tl_new:N \l__regex_every_match_tl \bool_new:N \l__regex_fresh_thread_bool \bool_new:N \l__regex_empty_success_bool @@ -1912,12 +1935,13 @@ \bool_gset_false:N \g__regex_success_bool \int_step_inline:nnnn \l__regex_min_state_int { 1 } { \l__regex_max_state_int - 1 } - { \tex_dimen:D ##1 ~ 1 sp \scan_stop: } + { \__intarray_gset_fast:Nnn \g__regex_state_active_intarray {##1} { 1 } } \int_set_eq:NN \l__regex_min_active_int \l__regex_max_state_int \int_zero:N \l__regex_step_int \int_set_eq:NN \l__regex_success_pos_int \l__regex_min_pos_int - \int_set:Nn \l__regex_submatch_int + \int_set:Nn \l__regex_min_submatch_int { 2 * \l__regex_max_state_int } + \int_set_eq:NN \l__regex_submatch_int \l__regex_min_submatch_int \bool_set_false:N \l__regex_empty_success_bool \__regex_match_once: } @@ -1958,7 +1982,7 @@ } \cs_new_protected:Npn \__regex_match_loop: { - \tex_advance:D \l__regex_step_int 2 \exp_stop_f: + \int_add:Nn \l__regex_step_int { 2 } \int_incr:N \l__regex_current_pos_int \int_set_eq:NN \l__regex_last_char_int \l__regex_current_char_int \int_set_eq:NN \l__regex_case_changed_char_int \c_max_int @@ -1966,8 +1990,11 @@ \use:x { \int_set_eq:NN \l__regex_max_active_int \l__regex_min_active_int - \exp_after:wN \__regex_match_one_active:w - \int_use:N \l__regex_min_active_int ; + \int_step_function:nnnN + { \l__regex_min_active_int } + { 1 } + { \l__regex_max_active_int - 1 } + \__regex_match_one_active:n } \__prg_break_point: \bool_set_false:N \l__regex_fresh_thread_bool %^^A was arg of break_point:n @@ -1977,25 +2004,21 @@ \fi: \fi: } -\cs_new:Npn \__regex_match_one_active:w #1; +\cs_new:Npn \__regex_match_one_active:n #1 { - \if_int_compare:w #1 < \l__regex_max_active_int - \__regex_use_state_and_submatches:nn - { \__int_value:w \tex_skip:D #1 } - { \tex_the:D \tex_toks:D #1 } - \exp_after:wN \__regex_match_one_active:w - \__int_value:w \__int_eval:w #1 + 1 \exp_after:wN ; - \fi: + \__regex_use_state_and_submatches:nn + { \__intarray_item_fast:Nn \g__regex_thread_state_intarray {#1} } + { \__regex_toks_use:w #1 } } \cs_new_protected:Npn \__regex_query_set:nnn #1#2#3 { - \tex_muskip:D \l__regex_current_pos_int - = \etex_gluetomu:D - #3 sp - plus #2 sp - minus \l__regex_balance_int sp - \scan_stop: - \tex_toks:D \l__regex_current_pos_int {#1} + \__intarray_gset_fast:Nnn \g__regex_charcode_intarray + { \l__regex_current_pos_int } {#3} + \__intarray_gset_fast:Nnn \g__regex_catcode_intarray + { \l__regex_current_pos_int } {#2} + \__intarray_gset_fast:Nnn \g__regex_balance_intarray + { \l__regex_current_pos_int } { \l__regex_balance_int } + \__regex_toks_set:Nn \l__regex_current_pos_int {#1} \int_incr:N \l__regex_current_pos_int \if_case:w #2 \exp_stop_f: \or: \int_incr:N \l__regex_balance_int @@ -2005,22 +2028,26 @@ \cs_new_protected:Npn \__regex_query_get: { \l__regex_current_char_int - = \etex_mutoglue:D \tex_muskip:D \l__regex_current_pos_int - \l__regex_current_catcode_int = \etex_gluestretch:D - \etex_mutoglue:D \tex_muskip:D \l__regex_current_pos_int + = \__intarray_item_fast:Nn \g__regex_charcode_intarray + { \l__regex_current_pos_int } \scan_stop: + \l__regex_current_catcode_int + = \__intarray_item_fast:Nn \g__regex_catcode_intarray + { \l__regex_current_pos_int } \scan_stop: } \cs_new_protected:Npn \__regex_use_state: { - \tex_dimen:D \l__regex_current_state_int - = \l__regex_step_int sp \scan_stop: - \tex_the:D \tex_toks:D \l__regex_current_state_int - \tex_dimen:D \l__regex_current_state_int - = \__int_eval:w \l__regex_step_int + 1 \__int_eval_end: sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_state_active_intarray + { \l__regex_current_state_int } { \l__regex_step_int } + \__regex_toks_use:w \l__regex_current_state_int + \__intarray_gset_fast:Nnn \g__regex_state_active_intarray + { \l__regex_current_state_int } { \l__regex_step_int + 1 } } \cs_new_protected:Npn \__regex_use_state_and_submatches:nn #1 #2 { \int_set:Nn \l__regex_current_state_int {#1} - \if_int_compare:w \tex_dimen:D \l__regex_current_state_int + \if_int_compare:w + \__intarray_item_fast:Nn \g__regex_state_active_intarray + { \l__regex_current_state_int } < \l__regex_step_int \tl_set:Nn \l__regex_current_submatches_prop {#2} \exp_after:wN \__regex_use_state: @@ -2045,7 +2072,10 @@ \int_add:Nn \l__regex_current_state_int {#2} \exp_not:n { - \if_int_compare:w \tex_dimen:D \l__regex_current_state_int #1 + \if_int_compare:w + \__intarray_item_fast:Nn \g__regex_state_active_intarray + { \l__regex_current_state_int } + #1 \exp_after:wN \__regex_use_state: \fi: } @@ -2063,12 +2093,13 @@ \cs_new_protected:Npn \__regex_store_state:n #1 { \__regex_store_submatches: - \tex_skip:D \l__regex_max_active_int = #1 sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_thread_state_intarray + { \l__regex_max_active_int } {#1} \int_incr:N \l__regex_max_active_int } \cs_new_protected:Npn \__regex_store_submatches: { - \tex_toks:D \l__regex_max_active_int \exp_after:wN + \__regex_toks_set:No \l__regex_max_active_int { \l__regex_current_submatches_prop } } \cs_new_protected:Npn \__regex_disable_submatches: @@ -2095,14 +2126,16 @@ } } \int_new:N \l__regex_replacement_csnames_int +\tl_new:N \l__regex_replacement_category_tl +\seq_new:N \l__regex_replacement_category_seq \tl_new:N \l__regex_balance_tl \cs_new:Npn \__regex_replacement_balance_one_match:n #1 { - \__regex_submatch_balance:n {#1} } \cs_new:Npn \__regex_replacement_do_one_match:n #1 { \__regex_query_range:nn - { \etex_glueshrink:D \tex_skip:D #1 } - { \tex_skip:D #1 } + { \__intarray_item_fast:Nn \g__regex_submatch_prev_intarray {#1} } + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {#1} } } \cs_new:Npn \__regex_replacement_exp_not:N #1 { \exp_not:n {#1} } \cs_new:Npn \__regex_query_range:nn #1#2 @@ -2118,22 +2151,35 @@ \else: \exp_after:wN \__prg_break: \fi: - \tex_the:D \tex_toks:D #1 \exp_stop_f: + \__regex_toks_use:w #1 \exp_stop_f: \exp_after:wN \__regex_query_range_loop:ww \__int_value:w \__int_eval:w #1 + 1 ; #2 ; } \cs_new:Npn \__regex_query_submatch:n #1 { \__regex_query_range:nn - { \tex_skip:D \__int_eval:w #1 } - { \etex_gluestretch:D \tex_skip:D \__int_eval:w #1 } + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {#1} } + { \__intarray_item_fast:Nn \g__regex_submatch_end_intarray {#1} } } \cs_new_protected:Npn \__regex_submatch_balance:n #1 { - \etex_glueshrink:D \etex_mutoglue:D \etex_muexpr:D - \tex_muskip:D \etex_gluestretch:D \tex_skip:D #1 - - \tex_muskip:D \tex_skip:D #1 - \scan_stop: + \__int_eval:w + \int_compare:nNnTF + { \__intarray_item_fast:Nn \g__regex_submatch_end_intarray {#1} } = 0 + { 0 } + { + \__intarray_item_fast:Nn \g__regex_balance_intarray + { \__intarray_item_fast:Nn \g__regex_submatch_end_intarray {#1} } + } + - + \int_compare:nNnTF + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {#1} } = 0 + { 0 } + { + \__intarray_item_fast:Nn \g__regex_balance_intarray + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {#1} } + } + \__int_eval_end: } \cs_new_protected:Npn \__regex_replacement:n #1 { @@ -2143,10 +2189,14 @@ \__regex_escape_use:nnnn { \if_charcode:w \c_right_brace_str ##1 - \__regex_replacement_rbrace:N \else: \__tl_build_one:n \fi: ##1 + \__regex_replacement_rbrace:N + \else: + \__regex_replacement_normal:n + \fi: + ##1 } { \__regex_replacement_escaped:N ##1 } - { \__tl_build_one:n ##1 } + { \__regex_replacement_normal:n ##1 } {#1} \prg_do_nothing: \prg_do_nothing: \if_int_compare:w \l__regex_replacement_csnames_int > 0 \exp_stop_f: @@ -2155,6 +2205,12 @@ \__tl_build_one:x { \prg_replicate:nn \l__regex_replacement_csnames_int \cs_end: } \fi: + \seq_if_empty:NF \l__regex_replacement_category_seq + { + \__msg_kernel_error:nnx { regex } { replacement-missing-rparen } + { \seq_count:N \l__regex_replacement_category_seq } + \seq_clear:N \l__regex_replacement_category_seq + } \cs_gset:Npx \__regex_replacement_balance_one_match:n ##1 { + \int_use:N \l__regex_balance_int @@ -2169,11 +2225,27 @@ \cs_set:Npn \__regex_replacement_do_one_match:n ##1 { \__regex_query_range:nn - { \etex_glueshrink:D \tex_skip:D ##1 } - { \tex_skip:D ##1 } + { \__intarray_item_fast:Nn \g__regex_submatch_prev_intarray {##1} } + { \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray {##1} } #1 } } +\cs_new_protected:Npn \__regex_replacement_normal:n #1 + { + \tl_if_empty:NTF \l__regex_replacement_category_tl + { \__tl_build_one:n {#1} } + { % ( + \token_if_eq_charcode:NNTF #1 ) + { + \seq_pop:NN \l__regex_replacement_category_seq + \l__regex_replacement_category_tl + } + { + \use:c { __regex_replacement_c_ \l__regex_replacement_category_tl :w } + \__regex_replacement_normal:n {#1} + } + } + } \cs_new_protected:Npn \__regex_replacement_escaped:N #1 { \cs_if_exist_use:cF { __regex_replacement_#1:w } @@ -2181,7 +2253,8 @@ \if_int_compare:w 1 < 1#1 \exp_stop_f: \__regex_replacement_put_submatch:n {#1} \else: - \__tl_build_one:o { \token_to_str:N #1 } + \exp_args:No \__regex_replacement_normal:n + { \token_to_str:N #1 } \fi: } } @@ -2197,28 +2270,26 @@ } \cs_new_protected:Npn \__regex_replacement_g:w #1#2 { - \str_if_eq_x:nnTF { #1#2 } { \__tl_build_one:n \c_left_brace_str } - { - \int_zero:N \l__regex_internal_a_int - \__regex_replacement_g_digits:NN - } + \str_if_eq_x:nnTF { #1#2 } { \__regex_replacement_normal:n \c_left_brace_str } + { \l__regex_internal_a_int = \__regex_replacement_g_digits:NN } { \__regex_replacement_error:NNN g #1 #2 } } -\cs_new_protected:Npn \__regex_replacement_g_digits:NN #1#2 +\cs_new:Npn \__regex_replacement_g_digits:NN #1#2 { - \token_if_eq_meaning:NNTF #1 \__tl_build_one:n + \token_if_eq_meaning:NNTF #1 \__regex_replacement_normal:n { \if_int_compare:w 1 < 1#2 \exp_stop_f: - \int_set:Nn \l__regex_internal_a_int - { 10 * \l__regex_internal_a_int + #2 } + #2 \exp_after:wN \use_i:nnn \exp_after:wN \__regex_replacement_g_digits:NN \else: + \exp_stop_f: \exp_after:wN \__regex_replacement_error:NNN \exp_after:wN g \fi: } { + \exp_stop_f: \if_meaning:w \__regex_replacement_rbrace:N #1 \exp_args:No \__regex_replacement_put_submatch:n { \int_use:N \l__regex_internal_a_int } @@ -2232,34 +2303,31 @@ } \cs_new_protected:Npn \__regex_replacement_c:w #1#2 { - \token_if_eq_meaning:NNTF #1 \__tl_build_one:n + \token_if_eq_meaning:NNTF #1 \__regex_replacement_normal:n { - \cs_if_exist_use:cF { __regex_replacement_c_#2:w } - { \__regex_replacement_error:NNN c #1#2 } + \exp_after:wN \token_if_eq_charcode:NNTF \c_left_brace_str #2 + { \__regex_replacement_cu_aux:Nw \__regex_replacement_exp_not:N } + { + \cs_if_exist:cTF { __regex_replacement_c_#2:w } + { \__regex_replacement_cat:NNN #2 } + { \__regex_replacement_error:NNN c #1#2 } + } } { \__regex_replacement_error:NNN c #1#2 } } -\cs_new_protected:cpn { __regex_replacement_c_ \c_left_brace_str :w } +\cs_new_protected:Npn \__regex_replacement_cu_aux:Nw #1 { \if_case:w \l__regex_replacement_csnames_int - \__tl_build_one:n - { \exp_not:n { \exp_after:wN \__regex_replacement_exp_not:N \cs:w } } + \__tl_build_one:n { \exp_not:n { \exp_after:wN #1 \cs:w } } \else: - \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:N \cs:w } } + \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:V \cs:w } } \fi: \int_incr:N \l__regex_replacement_csnames_int } \cs_new_protected:Npn \__regex_replacement_u:w #1#2 { - \str_if_eq_x:nnTF { #1#2 } { \__tl_build_one:n \c_left_brace_str } - { - \if_case:w \l__regex_replacement_csnames_int - \__tl_build_one:n { \exp_not:n { \exp_after:wN \exp_not:V \cs:w } } - \else: - \__tl_build_one:n { \exp_not:n { \exp_after:wN \tl_to_str:V \cs:w } } - \fi: - \int_incr:N \l__regex_replacement_csnames_int - } + \str_if_eq_x:nnTF { #1#2 } { \__regex_replacement_normal:n \c_left_brace_str } + { \__regex_replacement_cu_aux:Nw \exp_not:V } { \__regex_replacement_error:NNN u #1#2 } } \cs_new_protected:Npn \__regex_replacement_rbrace:N #1 @@ -2268,18 +2336,36 @@ \__tl_build_one:n \cs_end: \int_decr:N \l__regex_replacement_csnames_int \else: - \__tl_build_one:n #1 + \__regex_replacement_normal:n {#1} \fi: } +\cs_new_protected:Npn \__regex_replacement_cat:NNN #1#2#3 + { + \token_if_eq_meaning:NNTF \prg_do_nothing: #3 + { \__msg_kernel_error:nn { regex } { replacement-catcode-end } } + { + \int_compare:nNnTF { \l__regex_replacement_csnames_int } > 0 + { + \__msg_kernel_error:nnnn + { regex } { replacement-catcode-in-cs } {#1} {#3} + #2 #3 + } + { + \str_if_eq:nnTF { #2 #3 } { \__regex_replacement_normal:n ( } % ) + { + \seq_push:NV \l__regex_replacement_category_seq + \l__regex_replacement_category_tl + \tl_set:Nn \l__regex_replacement_category_tl {#1} + } + { \use:c { __regex_replacement_c_#1:w } #2 #3 } + } + } + } \group_begin: \cs_new_protected:Npn \__regex_replacement_char:nNN #1#2#3 { - \if_meaning:w \prg_do_nothing: #3 - \__msg_kernel_error:nn { regex } { replacement-catcode-end } - \else: - \tex_lccode:D 0 = `#3 \scan_stop: - \tex_lowercase:D { \__tl_build_one:n {#1} } - \fi: + \tex_lccode:D 0 = `#3 \scan_stop: + \tex_lowercase:D { \__tl_build_one:n {#1} } } \char_set_catcode_active:N \^^@ \cs_new_protected:Npn \__regex_replacement_c_A:w @@ -2324,15 +2410,11 @@ } \cs_new_protected:Npn \__regex_replacement_c_S:w #1#2 { - \if_meaning:w \prg_do_nothing: #2 - \__msg_kernel_error:nn { regex } { replacement-catcode-end } - \else: - \if_int_compare:w `#2 = 0 \exp_stop_f: - \__msg_kernel_error:nn { regex } { replacement-null-space } - \fi: - \tex_lccode:D `\ = `#2 \scan_stop: - \tex_lowercase:D { \__tl_build_one:n {~} } + \if_int_compare:w `#2 = 0 \exp_stop_f: + \__msg_kernel_error:nn { regex } { replacement-null-space } \fi: + \tex_lccode:D `\ = `#2 \scan_stop: + \tex_lowercase:D { \__tl_build_one:n {~} } } \char_set_catcode_alignment:N \^^@ \cs_new_protected:Npn \__regex_replacement_c_T:w @@ -2406,8 +2488,12 @@ \int_new:N \l__regex_match_count_int \flag_new:n { __regex_begin } \flag_new:n { __regex_end } +\int_new:N \l__regex_min_submatch_int \int_new:N \l__regex_submatch_int \int_new:N \l__regex_zeroth_submatch_int +\__intarray_new:Nn \g__regex_submatch_prev_intarray { 65536 } +\__intarray_new:Nn \g__regex_submatch_begin_intarray { 65536 } +\__intarray_new:Nn \g__regex_submatch_end_intarray { 65536 } \cs_new_protected:Npn \__regex_return: { \if_meaning:w \c_true_bool \g__regex_success_bool @@ -2461,15 +2547,29 @@ { \if_int_compare:w \l__regex_start_pos_int < \l__regex_success_pos_int \__regex_extract: - \tex_skip:D \l__regex_zeroth_submatch_int - = \l__regex_start_pos_int sp - plus \tex_skip:D \l__regex_zeroth_submatch_int \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_submatch_prev_intarray + { \l__regex_zeroth_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g__regex_submatch_end_intarray + { \l__regex_zeroth_submatch_int } + { + \__intarray_item_fast:Nn \g__regex_submatch_begin_intarray + { \l__regex_zeroth_submatch_int } + } + \__intarray_gset_fast:Nnn \g__regex_submatch_begin_intarray + { \l__regex_zeroth_submatch_int } + { \l__regex_start_pos_int } \fi: } #1 \__regex_match:n {#2} - \tex_skip:D \l__regex_submatch_int - = \l__regex_start_pos_int sp plus \l__regex_max_pos_int sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_submatch_prev_intarray + { \l__regex_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g__regex_submatch_end_intarray + { \l__regex_submatch_int } + { \l__regex_max_pos_int } + \__intarray_gset_fast:Nnn \g__regex_submatch_begin_intarray + { \l__regex_submatch_int } + { \l__regex_start_pos_int } \int_incr:N \l__regex_submatch_int \if_meaning:w \c_true_bool \l__regex_empty_success_bool \if_int_compare:w \l__regex_start_pos_int = \l__regex_max_pos_int @@ -2487,7 +2587,7 @@ { \s__seq \int_step_function:nnnN - { 2 * \l__regex_max_state_int } + { \l__regex_min_submatch_int } { 1 } { \l__regex_submatch_int - 1 } \__regex_extract_seq_aux:n @@ -2533,7 +2633,12 @@ \int_set_eq:NN \l__regex_zeroth_submatch_int \l__regex_submatch_int \prg_replicate:nn \l__regex_capturing_group_int { - \tex_skip:D \l__regex_submatch_int 0 sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_submatch_begin_intarray + { \l__regex_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g__regex_submatch_end_intarray + { \l__regex_submatch_int } { 0 } + \__intarray_gset_fast:Nnn \g__regex_submatch_prev_intarray + { \l__regex_submatch_int } { 0 } \int_incr:N \l__regex_submatch_int } \prop_map_inline:Nn \l__regex_success_submatches_prop @@ -2545,21 +2650,14 @@ \fi: \__int_eval:w \l__regex_zeroth_submatch_int + ##1 {##2} } - \tex_skip:D \l__regex_zeroth_submatch_int - = \tex_the:D \tex_skip:D \l__regex_zeroth_submatch_int - minus \l__regex_start_pos_int sp \scan_stop: + \__intarray_gset_fast:Nnn \g__regex_submatch_prev_intarray + { \l__regex_zeroth_submatch_int } { \l__regex_start_pos_int } \fi: } \cs_new_protected:Npn \__regex_extract_b:wn #1 < #2 - { - \tex_skip:D #1 = #2 sp - plus \etex_gluestretch:D \tex_skip:D #1 \scan_stop: - } + { \__intarray_gset_fast:Nnn \g__regex_submatch_begin_intarray {#1} {#2} } \cs_new_protected:Npn \__regex_extract_e:wn #1 > #2 - { - \tex_skip:D #1 - = 1 \tex_skip:D #1 plus #2 sp \scan_stop: - } + { \__intarray_gset_fast:Nnn \g__regex_submatch_end_intarray {#1} {#2} } \cs_new_protected:Npn \__regex_replace_once:nnN #1#2#3 { \group_begin: @@ -2580,7 +2678,10 @@ { \__regex_replacement_do_one_match:n { \l__regex_zeroth_submatch_int } \__regex_query_range:nn - { \etex_gluestretch:D \tex_skip:D \l__regex_zeroth_submatch_int } + { + \__intarray_item_fast:Nn \g__regex_submatch_end_intarray + { \l__regex_zeroth_submatch_int } + } { \l__regex_max_pos_int } } \__regex_group_end_replace:N #3 @@ -2597,7 +2698,7 @@ { 0 \int_step_function:nnnN - { 2 * \l__regex_max_state_int } + { \l__regex_min_submatch_int } \l__regex_capturing_group_int { \l__regex_submatch_int - 1 } \__regex_replacement_balance_one_match:n @@ -2605,7 +2706,7 @@ \tl_set:Nx \l__regex_internal_a_tl { \int_step_function:nnnN - { 2 * \l__regex_max_state_int } + { \l__regex_min_submatch_int } \l__regex_capturing_group_int { \l__regex_submatch_int - 1 } \__regex_replacement_do_one_match:n @@ -2641,38 +2742,38 @@ } } \__msg_kernel_new:nnnn { regex } { trailing-backslash } - { Trailing~escape~character~`\iow_char:N\\'. } + { Trailing~escape~character~'\iow_char:N\\'. } { A~regular~expression~or~its~replacement~text~ends~with~ - the~escape~character~`\iow_char:N\\'.~It~will~be~ignored. + the~escape~character~'\iow_char:N\\'.~It~will~be~ignored. } \__msg_kernel_new:nnnn { regex } { x-missing-rbrace } - { Missing~closing~brace~in~`\iow_char:N\\x'~hexadecimal~sequence. } + { Missing~closing~brace~in~'\iow_char:N\\x'~hexadecimal~sequence. } { You~wrote~something~like~ - `\iow_char:N\\x\{...#1'.~ + '\iow_char:N\\x\{...#1'.~ The~closing~brace~is~missing. } \__msg_kernel_new:nnnn { regex } { x-overflow } - { Character~code~`#1'~too~large~in~`\iow_char:N\\x'~hexadecimal~sequence. } + { Character~code~'#1'~too~large~in~'\iow_char:N\\x'~hexadecimal~sequence. } { You~wrote~something~like~ - `\iow_char:N\\x\{\int_to_Hex:n{#1}\}'.~ + '\iow_char:N\\x\{\int_to_Hex:n{#1}\}'.~ The~character~code~#1~is~larger~than~ the~maximum~value~\int_use:N \c_max_char_int. } \__msg_kernel_new:nnnn { regex } { invalid-quantifier } - { Braced~quantifier~`#1'~may~not~be~followed~by~`#2'. } + { Braced~quantifier~'#1'~may~not~be~followed~by~'#2'. } { - The~character~`#2'~is~invalid~in~the~braced~quantifier~`#1'.~ - The~only~valid~quantifiers~are~`*',~`?',~`+',~`{<int>}',~ - `{<min>,}'~and~`{<min>,<max>}',~optionally~followed~by~`?'. + The~character~'#2'~is~invalid~in~the~braced~quantifier~'#1'.~ + The~only~valid~quantifiers~are~'*',~'?',~'+',~'{<int>}',~ + '{<min>,}'~and~'{<min>,<max>}',~optionally~followed~by~'?'. } \__msg_kernel_new:nnnn { regex } { missing-rbrack } { Missing~right~bracket~inserted~in~regular~expression. } { LaTeX~was~given~a~regular~expression~where~a~character~class~ - was~started~with~`[',~but~the~matching~`]'~is~missing. + was~started~with~'[',~but~the~matching~']'~is~missing. } \__msg_kernel_new:nnnn { regex } { missing-rparen } { @@ -2692,7 +2793,7 @@ } \__msg_kernel_new:nnnn { regex } { bad-escape } { - Invalid~escape~`\iow_char:N\\#1'~ + Invalid~escape~'\iow_char:N\\#1'~ \__regex_if_in_cs:TF { within~a~control~sequence. } { \__regex_if_in_class:TF @@ -2701,102 +2802,102 @@ } } { - The~escape~sequence~`\iow_char:N\\#1'~may~not~appear~ + The~escape~sequence~'\iow_char:N\\#1'~may~not~appear~ \__regex_if_in_cs:TF { within~a~control~sequence~test~introduced~by~ - `\iow_char:N\\c\iow_char:N\{'. + '\iow_char:N\\c\iow_char:N\{'. } { \__regex_if_in_class:TF { within~a~character~class~ } - { following~a~category~test~such~as~`\iow_char:N\\cL'~ } + { following~a~category~test~such~as~'\iow_char:N\\cL'~ } because~it~does~not~match~exactly~one~character. } } \__msg_kernel_new:nnnn { regex } { range-missing-end } - { Invalid~end-point~for~range~`#1-#2'~in~character~class. } + { Invalid~end-point~for~range~'#1-#2'~in~character~class. } { - The~end-point~`#2'~of~the~range~`#1-#2'~may~not~serve~as~an~ + The~end-point~'#2'~of~the~range~'#1-#2'~may~not~serve~as~an~ end-point~for~a~range:~alphanumeric~characters~should~not~be~ escaped,~and~non-alphanumeric~characters~should~be~escaped. } \__msg_kernel_new:nnnn { regex } { range-backwards } - { Range~`[#1-#2]'~out~of~order~in~character~class. } + { Range~'[#1-#2]'~out~of~order~in~character~class. } { - In~ranges~of~characters~`[x-y]'~appearing~in~character~classes,~ + In~ranges~of~characters~'[x-y]'~appearing~in~character~classes,~ the~first~character~code~must~not~be~larger~than~the~second.~ - Here,~`#1'~has~character~code~\int_eval:n {`#1},~while~ - `#2'~has~character~code~\int_eval:n {`#2}. + Here,~'#1'~has~character~code~\int_eval:n {`#1},~while~ + '#2'~has~character~code~\int_eval:n {`#2}. } \__msg_kernel_new:nnnn { regex } { c-bad-mode } - { Invalid~nested~`\iow_char:N\\c'~escape~in~regular~expression. } + { Invalid~nested~'\iow_char:N\\c'~escape~in~regular~expression. } { - The~`\iow_char:N\\c'~escape~cannot~be~used~within~ - a~control~sequence~test~`\iow_char:N\\c{...}'.~ - To~combine~several~category~tests,~use~`\iow_char:N\\c[...]'. + The~'\iow_char:N\\c'~escape~cannot~be~used~within~ + a~control~sequence~test~'\iow_char:N\\c{...}'.~ + To~combine~several~category~tests,~use~'\iow_char:N\\c[...]'. } \__msg_kernel_new:nnnn { regex } { c-missing-rbrace } - { Missing~right~brace~inserted~for~`\iow_char:N\\c'~escape. } + { Missing~right~brace~inserted~for~'\iow_char:N\\c'~escape. } { LaTeX~was~given~a~regular~expression~where~a~ - `\iow_char:N\\c\iow_char:N\{...'~construction~was~not~ended~ - with~a~closing~brace~`\iow_char:N\}'. + '\iow_char:N\\c\iow_char:N\{...'~construction~was~not~ended~ + with~a~closing~brace~'\iow_char:N\}'. } \__msg_kernel_new:nnnn { regex } { c-missing-rbrack } - { Missing~right~bracket~inserted~for~`\iow_char:N\\c'~escape. } + { Missing~right~bracket~inserted~for~'\iow_char:N\\c'~escape. } { - A~construction~`\iow_char:N\\c[...'~appears~in~a~ - regular~expression,~but~the~closing~`]'~is~not~present. + A~construction~'\iow_char:N\\c[...'~appears~in~a~ + regular~expression,~but~the~closing~']'~is~not~present. } \__msg_kernel_new:nnnn { regex } { c-missing-category } - { Invalid~character~`#1'~following~`\iow_char:N\\c'~escape. } + { Invalid~character~'#1'~following~'\iow_char:N\\c'~escape. } { - In~regular~expressions,~the~`\iow_char:N\\c'~escape~sequence~ + In~regular~expressions,~the~'\iow_char:N\\c'~escape~sequence~ may~only~be~followed~by~a~left~brace,~a~left~bracket,~or~a~ capital~letter~representing~a~character~category,~namely~ - one~of~`ABCDELMOPSTU'. + one~of~'ABCDELMOPSTU'. } \__msg_kernel_new:nnnn { regex } { c-trailing } - { Trailing~category~code~escape~`\iow_char:N\\c'... } + { Trailing~category~code~escape~'\iow_char:N\\c'... } { - A~regular~expression~ends~with~`\iow_char:N\\c'~followed~ + A~regular~expression~ends~with~'\iow_char:N\\c'~followed~ by~a~letter.~It~will~be~ignored. } \__msg_kernel_new:nnnn { regex } { u-missing-lbrace } - { Missing~left~brace~following~`\iow_char:N\\u'~escape. } + { Missing~left~brace~following~'\iow_char:N\\u'~escape. } { - The~`\iow_char:N\\u'~escape~sequence~must~be~followed~by~ + The~'\iow_char:N\\u'~escape~sequence~must~be~followed~by~ a~brace~group~with~the~name~of~the~variable~to~use. } \__msg_kernel_new:nnnn { regex } { u-missing-rbrace } - { Missing~right~brace~inserted~for~`\iow_char:N\\u'~escape. } + { Missing~right~brace~inserted~for~'\iow_char:N\\u'~escape. } { LaTeX~ \str_if_eq_x:nnTF { } {#2} { reached~the~end~of~the~string~ } - { encountered~an~escaped~alphanumeric~character `\iow_char:N\\#2'~ } - when~parsing~the~argument~of~an~`\iow_char:N\\u\iow_char:N\{...\}'~escape. + { encountered~an~escaped~alphanumeric~character '\iow_char:N\\#2'~ } + when~parsing~the~argument~of~an~'\iow_char:N\\u\iow_char:N\{...\}'~escape. } \__msg_kernel_new:nnnn { regex } { posix-unsupported } - { POSIX~collating~element~`[#1 ~ #1]'~not~supported. } + { POSIX~collating~element~'[#1 ~ #1]'~not~supported. } { - The~`[.foo.]'~and~`[=bar=]'~syntaxes~have~a~special~meaning~ + The~'[.foo.]'~and~'[=bar=]'~syntaxes~have~a~special~meaning~ in~POSIX~regular~expressions.~This~is~not~supported~by~LaTeX.~ Maybe~you~forgot~to~escape~a~left~bracket~in~a~character~class? } \__msg_kernel_new:nnnn { regex } { posix-unknown } - { POSIX~class~`[:#1:]'~unknown. } + { POSIX~class~'[:#1:]'~unknown. } { - `[:#1:]'~is~not~among~the~known~POSIX~classes~ - `[:alnum:]',~`[:alpha:]',~`[:ascii:]',~`[:blank:]',~ - `[:cntrl:]',~`[:digit:]',~`[:graph:]',~`[:lower:]',~ - `[:print:]',~`[:punct:]',~`[:space:]',~`[:upper:]',~ - `[:word:]',~and~`[:xdigit:]'. + '[:#1:]'~is~not~among~the~known~POSIX~classes~ + '[:alnum:]',~'[:alpha:]',~'[:ascii:]',~'[:blank:]',~ + '[:cntrl:]',~'[:digit:]',~'[:graph:]',~'[:lower:]',~ + '[:print:]',~'[:punct:]',~'[:space:]',~'[:upper:]',~ + '[:word:]',~and~'[:xdigit:]'. } \__msg_kernel_new:nnnn { regex } { posix-missing-close } - { Missing~closing~`:]'~for~POSIX~class. } - { The~POSIX~syntax~`#1'~must~be~followed~by~`:]',~not~`#2'. } + { Missing~closing~':]'~for~POSIX~class. } + { The~POSIX~syntax~'#1'~must~be~followed~by~':]',~not~'#2'. } \__msg_kernel_new:nnnn { regex } { result-unbalanced } { Missing~brace~inserted~when~#1. } { @@ -2806,58 +2907,68 @@ #2~left,~#3~right. } \__msg_kernel_new:nnnn { regex } { unknown-option } - { Unknown~option~`#1'~for~regular~expressions. } + { Unknown~option~'#1'~for~regular~expressions. } { - The~only~available~option~is~`case-insensitive',~toggled~by~ - `(?i)'~and~`(?-i)'. + The~only~available~option~is~'case-insensitive',~toggled~by~ + '(?i)'~and~'(?-i)'. } \__msg_kernel_new:nnnn { regex } { special-group-unknown } - { Unknown~special~group~`#1~...'~in~a~regular~expression. } + { Unknown~special~group~'#1~...'~in~a~regular~expression. } { - The~only~valid~constructions~starting~with~`(?'~are~ - `(?:~...~)',~`(?|~...~)',~`(?i)',~and~`(?-i)'. + The~only~valid~constructions~starting~with~'(?'~are~ + '(?:~...~)',~'(?|~...~)',~'(?i)',~and~'(?-i)'. } \__msg_kernel_new:nnnn { regex } { replacement-c } - { Misused~`\iow_char:N\\c'~command~in~a~replacement~text. } + { Misused~'\iow_char:N\\c'~command~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\c'~escape~sequence~ - can~be~followed~by~one~of~the~letters~`ABCDELMOPSTU'~ - or~a~brace~group,~not~by~`#1'. + In~a~replacement~text,~the~'\iow_char:N\\c'~escape~sequence~ + can~be~followed~by~one~of~the~letters~'ABCDELMOPSTU'~ + or~a~brace~group,~not~by~'#1'. } \__msg_kernel_new:nnnn { regex } { replacement-u } - { Misused~`\iow_char:N\\u'~command~in~a~replacement~text. } + { Misused~'\iow_char:N\\u'~command~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\u'~escape~sequence~ + In~a~replacement~text,~the~'\iow_char:N\\u'~escape~sequence~ must~be~~followed~by~a~brace~group~holding~the~name~of~the~ variable~to~use. } \__msg_kernel_new:nnnn { regex } { replacement-g } { - Missing~brace~for~the~`\iow_char:N\\g'~construction~ + Missing~brace~for~the~'\iow_char:N\\g'~construction~ in~a~replacement~text. } { In~the~replacement~text~for~a~regular~expression~search,~ - submatches~are~represented~either~as~`\iow_char:N \\g{dd..d}',~ - or~`\\d',~where~`d'~are~single~digits.~Here,~a~brace~is~missing. + submatches~are~represented~either~as~'\iow_char:N \\g{dd..d}',~ + or~'\\d',~where~'d'~are~single~digits.~Here,~a~brace~is~missing. } \__msg_kernel_new:nnnn { regex } { replacement-catcode-end } { - Missing~character~for~the~`\iow_char:N\\c<category><character>'~ + Missing~character~for~the~'\iow_char:N\\c<category><character>'~ construction~in~a~replacement~text. } { - In~a~replacement~text,~the~`\iow_char:N\\c'~escape~sequence~ - can~be~followed~by~one~of~the~letters~`ABCDELMOPSTU'~representing~ + In~a~replacement~text,~the~'\iow_char:N\\c'~escape~sequence~ + can~be~followed~by~one~of~the~letters~'ABCDELMOPSTU'~representing~ the~character~category.~Then,~a~character~must~follow.~LaTeX~ reached~the~end~of~the~replacement~when~looking~for~that. } +\__msg_kernel_new:nnnn { regex } { replacement-catcode-in-cs } + { + Category~code~'\iow_char:N\\c#1#3'~ignored~inside~ + '\iow_char:N\\c\{...\}'~in~a~replacement~text. + } + { + In~a~replacement~text,~the~category~codes~of~the~argument~of~ + '\iow_char:N\\c\{...\}'~are~ignored~when~building~the~control~ + sequence~name. + } \__msg_kernel_new:nnnn { regex } { replacement-null-space } { TeX~cannot~build~a~space~token~with~character~code~0. } { You~asked~for~a~character~token~with~category~space,~ and~character~code~0,~for~instance~through~ - `\iow_char:N\\cS\iow_char:N\\x00'.~ + '\iow_char:N\\cS\iow_char:N\\x00'.~ This~specific~case~is~impossible~and~will~be~replaced~ by~a~normal~space. } @@ -2867,6 +2978,12 @@ There~ \int_compare:nTF { #1 = 1 } { was } { were } ~ #1~ missing~right~\int_compare:nTF { #1 = 1 } { brace } { braces } . } +\__msg_kernel_new:nnnn { regex } { replacement-missing-rparen } + { Missing~right~parenthesis~inserted~in~replacement~text. } + { + There~ \int_compare:nTF { #1 = 1 } { was } { were } ~ #1~ + missing~right~\int_compare:nTF { #1 = 1 } { parenthesis } { parentheses } . + } \cs_new:Npn \__regex_msg_repeated:nnN #1#2#3 { \str_if_eq_x:nnF { #1 #2 } { 1 0 } diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-convert.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-convert.sty index d7998754945..b7216bd406a 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-convert.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-convert.sty @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `package') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of @@ -20,7 +20,7 @@ %% %% File: l3str-convert.dtx Copyright (C) 2013-2017 The LaTeX3 Project \RequirePackage{expl3} -\ProvidesExplPackage{l3str-convert}{2017/04/01}{} +\ProvidesExplPackage{l3str-convert}{2017/05/13}{} {L3 Experimental string encoding conversions} \RequirePackage{l3tl-analysis,l3tl-build} \cs_if_exist:NF \use_ii_i:nn @@ -31,10 +31,6 @@ \tl_new:N \g__str_result_tl \int_const:Nn \c__str_replacement_char_int { "FFFD } \int_const:Nn \c__str_max_byte_int { 255 } -\int_const:Nn \c__str_ascii_min_int { 0 } -\int_const:Nn \c__str_ascii_max_control_int { 31 } -\int_const:Nn \c__str_ascii_max_int { 127 } -\int_const:Nn \c__str_ascii_lower_int { `a - `A } \prop_new:N \g__str_alias_prop \prop_gput:Nnn \g__str_alias_prop { latin1 } { iso88591 } \prop_gput:Nnn \g__str_alias_prop { latin2 } { iso88592 } @@ -54,32 +50,6 @@ \bool_new:N \g__str_error_bool \flag_new:n { str_byte } \flag_new:n { str_error } -\group_begin: -\char_set_lccode:nn { `\* } { `\ } -\char_set_lccode:nn { `\A } { `\A } -\tex_lowercase:D - { - \group_end: - \cs_new_protected:Npn \__str_gset_other:Nn #1#2 - { - \tl_gset:Nx #1 - { - \exp_after:wN \__str_gset_other_loop:w \tl_to_str:n {#2} ~ % - A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_stop - } - } - \cs_new:Npn \__str_gset_other_loop:w - #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 ~ - { - \if_meaning:w A #9 - \__str_gset_other_end:w - \fi: - #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * #9 - \__str_gset_other_loop:w * - } - \cs_new:Npn \__str_gset_other_end:w \fi: #1 * A #2 \q_stop - { \fi: #1 } - } \prg_new_conditional:Npnn \__str_if_contains_char:NN #1#2 { T , TF } { \exp_after:wN \__str_if_contains_char_aux:NN \exp_after:wN #2 @@ -245,7 +215,7 @@ { \group_begin: #1 - \__str_gset_other:Nn \g__str_result_tl {#4} + \tl_gset:Nx \g__str_result_tl { \__str_to_other_fast:n {#4} } \exp_after:wN \__str_convert:wwwnn \tl_to_str:n {#5} /// \q_stop { decode } { unescape } @@ -335,7 +305,7 @@ #1 \fi: \else: - \__str_output_byte:n { `#1 + \c__str_ascii_lower_int } + \__str_output_byte:n { `#1 + `a - `A } \fi: \fi: \__str_convert_lowercase_alphanum_loop:N diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88591.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88591.def index 4ec7d5c8d75..60be5c7f1b2 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88591.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88591.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88591') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885910.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885910.def index 6aed0dcb9ef..a651b227cc1 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885910.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885910.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso885910') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885911.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885911.def index f551a2ac4ad..1a48cc8bec3 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885911.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885911.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso885911') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885913.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885913.def index 1c44066f1af..948072f8ac6 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885913.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885913.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso885913') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885914.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885914.def index 75814fbb8ad..6faf3e101b2 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885914.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885914.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso885914') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885915.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885915.def index fb0bba2e5ad..f6846a10f99 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885915.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885915.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso885915') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885916.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885916.def index 89d59900f77..ef5c375d337 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885916.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso885916.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso885916') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88592.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88592.def index 584fb3de28b..9b036d2488f 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88592.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88592.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88592') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88593.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88593.def index 3ec8d60de3f..f7014f192af 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88593.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88593.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88593') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88594.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88594.def index c2c3aaf7ed3..d388165099a 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88594.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88594.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88594') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88595.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88595.def index 9a22152f36e..d9f12eed1da 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88595.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88595.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88595') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88596.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88596.def index 37d058df1ac..0431f27c25d 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88596.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88596.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88596') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88597.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88597.def index 101b2225c5c..d7358bdb9b1 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88597.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88597.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88597') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88598.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88598.def index 8183ea85048..68f7b576f29 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88598.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88598.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88598') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88599.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88599.def index 0f6bf25306e..4ac243c585c 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88599.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-iso88599.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `iso88599') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf16.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf16.def index 431b242f550..f180be34a57 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf16.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf16.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `utf16') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf32.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf32.def index 6f466ba400d..c1c2c5ca595 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf32.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf32.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `utf32') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf8.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf8.def index 4518878b883..c3bc0506f64 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf8.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-enc-utf8.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `utf8') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-hex.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-hex.def index 3a5e52a5fdc..d3ed4b3c947 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-hex.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-hex.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `hex') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-name.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-name.def index b01837f7369..150e208bafb 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-name.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-name.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `name') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-string.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-string.def index 83982d00b9f..b2c8c75fbd0 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-string.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-string.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `string') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-url.def b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-url.def index 8176cf9106e..5459b12971b 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-url.def +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-esc-url.def @@ -6,7 +6,7 @@ %% %% l3str-convert.dtx (with options: `url') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-format.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-format.sty index 8c2f7a98001..abbaec08ea3 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-format.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-format.sty @@ -6,7 +6,7 @@ %% %% l3str-format.dtx (with options: `package') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of @@ -20,7 +20,7 @@ %% %% File: l3str-format.dtx Copyright (C) 2012-2013,2015-2017 The LaTeX3 Project \RequirePackage{expl3} -\ProvidesExplPackage{l3str-format}{2017/04/01}{} +\ProvidesExplPackage{l3str-format}{2017/05/13}{} {L3 Experimental string formatting} \RequirePackage{l3str} \cs_generate_variant:Nn \use:nn { nf } diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty index 0a8ca847851..9b336143d14 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-analysis.sty @@ -6,7 +6,7 @@ %% %% l3tl-analysis.dtx (with options: `package') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of @@ -20,7 +20,7 @@ %% %% File: l3tl-analysis.dtx Copyright (C) 2011-2012,2015-2017 The LaTeX3 Project \RequirePackage{expl3} -\ProvidesExplPackage{l3tl-analysis}{2017/04/01}{} +\ProvidesExplPackage{l3tl-analysis}{2017/05/13}{} {L3 Experimental token list analysis} \__scan_new:N \s__tl \tl_new:N \l__tl_analysis_internal_tl @@ -67,8 +67,9 @@ { \int_set:Nn \tex_escapechar:D { -1 } \exp_after:wN \__tl_analysis_disable_loop:N - \tl_to_str:n {#1} { ~ } { ? ~ \__prg_break: } + \tl_to_str:n {#1} { ~ } { ? \__prg_break: } \__prg_break_point: + \scan_stop: } \group_begin: \char_set_catcode_active:N \^^@ @@ -78,6 +79,20 @@ \tex_lowercase:D { \tex_let:D ^^@ } \tex_undefined:D \__tl_analysis_disable_loop:N } + \bool_lazy_or:nnT + { \sys_if_engine_ptex_p: } + { \sys_if_engine_uptex_p: } + { + \cs_gset_protected:Npn \__tl_analysis_disable_loop:N #1 + { + \use_none:n #1 \scan_stop: + \if_int_compare:w 256 > `#1 \exp_stop_f: + \tex_lccode:D 0 = `#1 ~ + \tex_lowercase:D { \tex_let:D ^^@ } \tex_undefined:D + \fi: + \__tl_analysis_disable_loop:N + } + } \group_end: \cs_new_protected:Npn \__tl_analysis_a:n #1 { diff --git a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-build.sty b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-build.sty index a176d86fde3..9feca451233 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-build.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/l3str/l3tl-build.sty @@ -6,7 +6,7 @@ %% %% l3tl-build.dtx (with options: `package') %% -%% Copyright (C) 2011-2016 The LaTeX3 Project +%% Copyright (C) 2011-2017 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of @@ -19,8 +19,8 @@ %% and all files in that bundle must be distributed together. %% %% File: l3tl-build.dtx Copyright (C) 2011-2017 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{l3tl-build}{Support package l3kernel too old} @@ -32,7 +32,7 @@ }% \endinput } -\ProvidesExplPackage{l3tl-build}{2017/04/01}{} +\ProvidesExplPackage{l3tl-build}{2017/05/13}{} {L3 Experimental token list construction} \int_new:N \l__tl_build_start_index_int \int_new:N \l__tl_build_index_int diff --git a/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty b/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty index 9df0824a280..1e2905d4cf4 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty @@ -20,7 +20,7 @@ %% %% File: xcoffins.dtx Copyright(C) 2010-2012,2014,2016,2017 The LaTeX3 Project \RequirePackage{xparse} -\ProvidesExplPackage{xcoffins}{2017/04/01}{} +\ProvidesExplPackage{xcoffins}{2017/05/13}{} {L3 Experimental design level coffins} \keys_define:nn { coffin } { diff --git a/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty b/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty index 6318649f93e..f4e6e5574f4 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty @@ -20,8 +20,8 @@ %% %% File: l3galley.dtx Copyright (C) 1999-2001, 2004-2009 Frank Mittelbach %% (C) 2010-2017 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{l3galley}{Support package l3kernel too old} @@ -33,7 +33,7 @@ }% \endinput } -\ProvidesExplPackage{l3galley}{2017/04/01}{} +\ProvidesExplPackage{l3galley}{2017/05/13}{} {L3 Experimental galley code} \int_new:N \l__galley_tmp_int \seq_new:N \g__galley_tmpa_seq @@ -274,7 +274,7 @@ \cs_new_protected:Npn \galley_par:n #1 { \s__par_omit - \bool_if:nF \g__galley_begin_level_bool + \bool_if:NF \g__galley_begin_level_bool { #1 \galley_par: diff --git a/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty b/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty index 8027687f2eb..13e44bce0fd 100644 --- a/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty +++ b/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty @@ -21,7 +21,7 @@ %% File: xgalley.dtx Copyright (C) 1999-2001, 2004-2009 Frank Mittelbach %% (C) 2010-2012,2014,2016-2017 The LaTeX3 Project \RequirePackage{xparse} -\ProvidesExplPackage{xgalley}{2017/04/01}{} +\ProvidesExplPackage{xgalley}{2017/05/13}{} {L3 Experimental galley} \RequirePackage{xparse,xtemplate,l3galley} \clist_new:N \l__galley_tmpa_clist diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex b/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex index f0604e11f7c..16769c81796 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex +++ b/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex @@ -58,7 +58,7 @@ %% and all files in that bundle must be distributed together. %% %% File: expl3.dtx Copyright (C) 1990-2017 The LaTeX3 Project -\def\ExplFileDate{2017/04/01}% +\def\ExplFileDate{2017/05/13}% \begingroup \def\next{\endgroup}% \expandafter\ifx\csname PackageError\endcsname\relax @@ -3064,7 +3064,8 @@ \cs_new_protected:Npn \tl_map_inline:nn #1#2 { \int_gincr:N \g__prg_map_int - \cs_gset:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} + \cs_gset_protected:cpn + { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} \exp_args:Nc \__tl_map_function:Nn { __prg_map_ \int_use:N \g__prg_map_int :w } #1 \q_recursion_tail @@ -4788,7 +4789,7 @@ \cs_generate_variant:Nn \int_gincr:N { c } \cs_generate_variant:Nn \int_gdecr:N { c } \cs_new_protected:Npn \int_set:Nn #1#2 - { #1 ~ \__int_eval:w #2\__int_eval_end: } + { #1 ~ \__int_eval:w #2 \__int_eval_end: } \cs_new_protected:Npn \int_gset:Nn { \tex_global:D \int_set:Nn } \cs_generate_variant:Nn \int_set:Nn { c } \cs_generate_variant:Nn \int_gset:Nn { c } @@ -5005,14 +5006,14 @@ { \int_gincr:N \g__prg_map_int \exp_args:NNc \__int_step:NNnnnn - \cs_gset:Npn + \cs_gset_protected:Npn { __prg_map_ \int_use:N \g__prg_map_int :w } } \cs_new_protected:Npn \int_step_variable:nnnNn #1#2#3#4#5 { \int_gincr:N \g__prg_map_int \exp_args:NNc \__int_step:NNnnnn - \cs_gset:Npx + \cs_gset_protected:Npx { __prg_map_ \int_use:N \g__prg_map_int :w } {#1}{#2}{#3} { @@ -6307,7 +6308,8 @@ \clist_if_empty:NF #1 { \int_gincr:N \g__prg_map_int - \cs_gset:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} + \cs_gset_protected:cpn + { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} \exp_last_unbraced:Nco \__clist_map_function:Nw { __prg_map_ \int_use:N \g__prg_map_int :w } #1 , \q_recursion_tail , @@ -7474,7 +7476,7 @@ \cs_gset_eq:cN { __prg_map_ \int_use:N \g__prg_map_int :wn } \__prop_pair:wn \int_gincr:N \g__prg_map_int - \cs_gset:Npn \__prop_pair:wn ##1 \s__prop ##2 {#2} + \cs_gset_protected:Npn \__prop_pair:wn ##1 \s__prop ##2 {#2} #1 \__prg_break_point:Nn \prop_map_break: { @@ -11329,10 +11331,13 @@ { \cs_if_exist_use:cF { __fp_parse_word_#2:N } { - \__msg_kernel_expandable_error:nnn - { kernel } { unknown-fp-word } {#2} - \exp_after:wN \c_nan_fp \exp:w \exp_end_continue_f:w - \__fp_parse_infix:NN + \cs_if_exist_use:cF { __fp_parse_caseless_ \str_fold_case:n {#2} :N } + { + \__msg_kernel_expandable_error:nnn + { kernel } { unknown-fp-word } {#2} + \exp_after:wN \c_nan_fp \exp:w \exp_end_continue_f:w + \__fp_parse_infix:NN + } } #1 } @@ -11823,6 +11828,9 @@ \__fp_tmp:w { deg } \c_one_degree_fp \__fp_tmp:w { true } \c_one_fp \__fp_tmp:w { false } \c_zero_fp +\cs_new_eq:NN \__fp_parse_caseless_inf:N \__fp_parse_word_inf:N +\cs_new_eq:NN \__fp_parse_caseless_infinity:N \__fp_parse_word_inf:N +\cs_new_eq:NN \__fp_parse_caseless_nan:N \__fp_parse_word_nan:N \cs_set_protected:Npn \__fp_tmp:w #1 #2 { \cs_new:cpn { __fp_parse_word_#1:N } @@ -12512,13 +12520,29 @@ } } \cs_generate_variant:Nn \__fp_step:NnnnnN { Nf } -\cs_new_protected:Npn \fp_step_inline:nnnn #1#2#3#4 +\cs_new_protected:Npn \fp_step_inline:nnnn + { + \int_gincr:N \g__prg_map_int + \exp_args:NNc \__fp_step:NNnnnn + \cs_gset_protected:Npn + { __prg_map_ \int_use:N \g__prg_map_int :w } + } +\cs_new_protected:Npn \fp_step_variable:nnnNn #1#2#3#4#5 { \int_gincr:N \g__prg_map_int - \cs_gset_protected:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } - ##1 {#4} - \fp_step_function:nnnc {#1} {#2} {#3} + \exp_args:NNc \__fp_step:NNnnnn + \cs_gset_protected:Npx { __prg_map_ \int_use:N \g__prg_map_int :w } + {#1} {#2} {#3} + { + \tl_set:Nn \exp_not:N #4 {##1} + \exp_not:n {#5} + } + } +\cs_new_protected:Npn \__fp_step:NNnnnn #1#2#3#4#5#6 + { + #1 #2 ##1 {#6} + \fp_step_function:nnnN {#3} {#4} {#5} #2 \__prg_break_point:Nn \scan_stop: { \int_gdecr:N \g__prg_map_int } } \__msg_kernel_new:nnn { kernel } { fp-bad-step } @@ -16320,29 +16344,45 @@ } } \cs_generate_variant:Nn \__box_show:NNnn { NNff } -\cs_new_protected:Npn \hbox:n #1 { \tex_hbox:D \scan_stop: {#1} } +\cs_new_protected:Npn \hbox:n #1 + { \tex_hbox:D \scan_stop: { \group_begin: #1 \group_end: } } \cs_new_protected:Npn \hbox_set:Nn #1#2 - { \tex_setbox:D #1 \tex_hbox:D {#2} } + { \tex_setbox:D #1 \tex_hbox:D { \group_begin: #2 \group_end: } } \cs_new_protected:Npn \hbox_gset:Nn { \tex_global:D \hbox_set:Nn } \cs_generate_variant:Nn \hbox_set:Nn { c } \cs_generate_variant:Nn \hbox_gset:Nn { c } \cs_new_protected:Npn \hbox_set_to_wd:Nnn #1#2#3 - { \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:w #2 \__dim_eval_end: {#3} } + { + \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:w #2 \__dim_eval_end: + { \group_begin: #3 \group_end: } + } \cs_new_protected:Npn \hbox_gset_to_wd:Nnn { \tex_global:D \hbox_set_to_wd:Nnn } \cs_generate_variant:Nn \hbox_set_to_wd:Nnn { c } \cs_generate_variant:Nn \hbox_gset_to_wd:Nnn { c } \cs_new_protected:Npn \hbox_set:Nw #1 - { \tex_setbox:D #1 \tex_hbox:D \c_group_begin_token } + { + \tex_setbox:D #1 \tex_hbox:D + \c_group_begin_token + \group_begin: + } \cs_new_protected:Npn \hbox_gset:Nw { \tex_global:D \hbox_set:Nw } \cs_generate_variant:Nn \hbox_set:Nw { c } \cs_generate_variant:Nn \hbox_gset:Nw { c } -\cs_new_eq:NN \hbox_set_end: \c_group_end_token -\cs_new_eq:NN \hbox_gset_end: \c_group_end_token +\cs_new_protected:Npn \hbox_set_end: + { + \group_end: + \c_group_end_token + } +\cs_new_eq:NN \hbox_gset_end: \hbox_set_end: \cs_new_protected:Npn \hbox_to_wd:nn #1#2 - { \tex_hbox:D to \__dim_eval:w #1 \__dim_eval_end: {#2} } -\cs_new_protected:Npn \hbox_to_zero:n #1 { \tex_hbox:D to \c_zero_dim {#1} } + { + \tex_hbox:D to \__dim_eval:w #1 \__dim_eval_end: + { \group_begin: #2 \group_end: } + } +\cs_new_protected:Npn \hbox_to_zero:n #1 + { \tex_hbox:D to \c_zero_dim { \group_begin: #1 \group_end: } } \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 @@ -16351,19 +16391,33 @@ \cs_new_eq:NN \hbox_unpack_clear:N \tex_unhbox:D \cs_generate_variant:Nn \hbox_unpack:N { c } \cs_generate_variant:Nn \hbox_unpack_clear:N { c } -\cs_new_protected:Npn \vbox:n #1 { \tex_vbox:D { #1 \par } } -\cs_new_protected:Npn \vbox_top:n #1 { \tex_vtop:D { #1 \par } } +\cs_new_protected:Npn \vbox:n #1 + { \tex_vbox:D { \group_begin: #1 \par \group_end: } } +\cs_new_protected:Npn \vbox_top:n #1 + { \tex_vtop:D { \group_begin: #1 \par \group_end: } } \cs_new_protected:Npn \vbox_to_ht:nn #1#2 - { \tex_vbox:D to \__dim_eval:w #1 \__dim_eval_end: { #2 \par } } + { + \tex_vbox:D to \__dim_eval:w #1 \__dim_eval_end: + { \group_begin: #2 \par \group_end: } + } \cs_new_protected:Npn \vbox_to_zero:n #1 - { \tex_vbox:D to \c_zero_dim { #1 \par } } + { + \tex_vbox:D to \c_zero_dim + { \group_begin: #1 \par \group_end: } + } \cs_new_protected:Npn \vbox_set:Nn #1#2 - { \tex_setbox:D #1 \tex_vbox:D { #2 \par } } + { + \tex_setbox:D #1 \tex_vbox:D + { \group_begin: #2 \par \group_end: } + } \cs_new_protected:Npn \vbox_gset:Nn { \tex_global:D \vbox_set:Nn } \cs_generate_variant:Nn \vbox_set:Nn { c } \cs_generate_variant:Nn \vbox_gset:Nn { c } \cs_new_protected:Npn \vbox_set_top:Nn #1#2 - { \tex_setbox:D #1 \tex_vtop:D { #2 \par } } + { + \tex_setbox:D #1 \tex_vtop:D + { \group_begin: #2 \par \group_end: } + } \cs_new_protected:Npn \vbox_gset_top:Nn { \tex_global:D \vbox_set_top:Nn } \cs_generate_variant:Nn \vbox_set_top:Nn { c } @@ -16371,21 +16425,26 @@ \cs_new_protected:Npn \vbox_set_to_ht:Nnn #1#2#3 { \tex_setbox:D #1 \tex_vbox:D to \__dim_eval:w #2 \__dim_eval_end: - { #3 \par } + { \group_begin: #3 \par \group_end: } } \cs_new_protected:Npn \vbox_gset_to_ht:Nnn { \tex_global:D \vbox_set_to_ht:Nnn } \cs_generate_variant:Nn \vbox_set_to_ht:Nnn { c } \cs_generate_variant:Nn \vbox_gset_to_ht:Nnn { c } \cs_new_protected:Npn \vbox_set:Nw #1 - { \tex_setbox:D #1 \tex_vbox:D \c_group_begin_token } + { + \tex_setbox:D #1 \tex_vbox:D + \c_group_begin_token + \group_begin: + } \cs_new_protected:Npn \vbox_gset:Nw { \tex_global:D \vbox_set:Nw } \cs_generate_variant:Nn \vbox_set:Nw { c } \cs_generate_variant:Nn \vbox_gset:Nw { c } \cs_new_protected:Npn \vbox_set_end: { - \par + \par + \group_end: \c_group_end_token } \cs_new_eq:NN \vbox_gset_end: \vbox_set_end: @@ -16395,21 +16454,322 @@ \cs_generate_variant:Nn \vbox_unpack_clear:N { c } \cs_new_protected:Npn \vbox_set_split_to_ht:NNn #1#2#3 { \tex_setbox:D #1 \tex_vsplit:D #2 to \__dim_eval:w #3 \__dim_eval_end: } +\fp_new:N \l__box_angle_fp +\fp_new:N \l__box_cos_fp +\fp_new:N \l__box_sin_fp +\dim_new:N \l__box_top_dim +\dim_new:N \l__box_bottom_dim +\dim_new:N \l__box_left_dim +\dim_new:N \l__box_right_dim +\dim_new:N \l__box_top_new_dim +\dim_new:N \l__box_bottom_new_dim +\dim_new:N \l__box_left_new_dim +\dim_new:N \l__box_right_new_dim +\box_new:N \l__box_internal_box +\cs_new_protected:Npn \box_rotate:Nn #1#2 + { + \hbox_set:Nn #1 + { + \fp_set:Nn \l__box_angle_fp {#2} + \fp_set:Nn \l__box_sin_fp { sind ( \l__box_angle_fp ) } + \fp_set:Nn \l__box_cos_fp { cosd ( \l__box_angle_fp ) } + \__box_rotate:N #1 + } + } +\cs_new_protected:Npn \__box_rotate:N #1 + { + \dim_set:Nn \l__box_top_dim { \box_ht:N #1 } + \dim_set:Nn \l__box_bottom_dim { -\box_dp:N #1 } + \dim_set:Nn \l__box_right_dim { \box_wd:N #1 } + \dim_zero:N \l__box_left_dim + \fp_compare:nNnTF \l__box_sin_fp > \c_zero_fp + { + \fp_compare:nNnTF \l__box_cos_fp > \c_zero_fp + { \__box_rotate_quadrant_one: } + { \__box_rotate_quadrant_two: } + } + { + \fp_compare:nNnTF \l__box_cos_fp < \c_zero_fp + { \__box_rotate_quadrant_three: } + { \__box_rotate_quadrant_four: } + } + \hbox_set:Nn \l__box_internal_box { \box_use:N #1 } + \hbox_set:Nn \l__box_internal_box + { + \tex_kern:D -\l__box_left_new_dim + \hbox:n + { + \__driver_box_use_rotate:Nn + \l__box_internal_box + \l__box_angle_fp + } + } + \box_set_ht:Nn \l__box_internal_box { \l__box_top_new_dim } + \box_set_dp:Nn \l__box_internal_box { -\l__box_bottom_new_dim } + \box_set_wd:Nn \l__box_internal_box + { \l__box_right_new_dim - \l__box_left_new_dim } + \box_use:N \l__box_internal_box + } +\cs_new_protected:Npn \__box_rotate_x:nnN #1#2#3 + { + \dim_set:Nn #3 + { + \fp_to_dim:n + { + \l__box_cos_fp * \dim_to_fp:n {#1} + - \l__box_sin_fp * \dim_to_fp:n {#2} + } + } + } +\cs_new_protected:Npn \__box_rotate_y:nnN #1#2#3 + { + \dim_set:Nn #3 + { + \fp_to_dim:n + { + \l__box_sin_fp * \dim_to_fp:n {#1} + + \l__box_cos_fp * \dim_to_fp:n {#2} + } + } + } +\cs_new_protected:Npn \__box_rotate_quadrant_one: + { + \__box_rotate_y:nnN \l__box_right_dim \l__box_top_dim + \l__box_top_new_dim + \__box_rotate_y:nnN \l__box_left_dim \l__box_bottom_dim + \l__box_bottom_new_dim + \__box_rotate_x:nnN \l__box_left_dim \l__box_top_dim + \l__box_left_new_dim + \__box_rotate_x:nnN \l__box_right_dim \l__box_bottom_dim + \l__box_right_new_dim + } +\cs_new_protected:Npn \__box_rotate_quadrant_two: + { + \__box_rotate_y:nnN \l__box_right_dim \l__box_bottom_dim + \l__box_top_new_dim + \__box_rotate_y:nnN \l__box_left_dim \l__box_top_dim + \l__box_bottom_new_dim + \__box_rotate_x:nnN \l__box_right_dim \l__box_top_dim + \l__box_left_new_dim + \__box_rotate_x:nnN \l__box_left_dim \l__box_bottom_dim + \l__box_right_new_dim + } +\cs_new_protected:Npn \__box_rotate_quadrant_three: + { + \__box_rotate_y:nnN \l__box_left_dim \l__box_bottom_dim + \l__box_top_new_dim + \__box_rotate_y:nnN \l__box_right_dim \l__box_top_dim + \l__box_bottom_new_dim + \__box_rotate_x:nnN \l__box_right_dim \l__box_bottom_dim + \l__box_left_new_dim + \__box_rotate_x:nnN \l__box_left_dim \l__box_top_dim + \l__box_right_new_dim + } +\cs_new_protected:Npn \__box_rotate_quadrant_four: + { + \__box_rotate_y:nnN \l__box_left_dim \l__box_top_dim + \l__box_top_new_dim + \__box_rotate_y:nnN \l__box_right_dim \l__box_bottom_dim + \l__box_bottom_new_dim + \__box_rotate_x:nnN \l__box_left_dim \l__box_bottom_dim + \l__box_left_new_dim + \__box_rotate_x:nnN \l__box_right_dim \l__box_top_dim + \l__box_right_new_dim + } +\fp_new:N \l__box_scale_x_fp +\fp_new:N \l__box_scale_y_fp +\cs_new_protected:Npn \box_resize_to_wd_and_ht_plus_dp:Nnn #1#2#3 + { + \hbox_set:Nn #1 + { + \__box_resize_set_corners:N #1 + \fp_set:Nn \l__box_scale_x_fp + { \dim_to_fp:n {#2} / \dim_to_fp:n { \l__box_right_dim } } + \fp_set:Nn \l__box_scale_y_fp + { + \dim_to_fp:n {#3} + / \dim_to_fp:n { \l__box_top_dim - \l__box_bottom_dim } + } + \__box_resize:N #1 + } + } +\cs_generate_variant:Nn \box_resize_to_wd_and_ht_plus_dp:Nnn { c } +\cs_new_protected:Npn \__box_resize_set_corners:N #1 + { + \dim_set:Nn \l__box_top_dim { \box_ht:N #1 } + \dim_set:Nn \l__box_bottom_dim { -\box_dp:N #1 } + \dim_set:Nn \l__box_right_dim { \box_wd:N #1 } + \dim_zero:N \l__box_left_dim + } +\cs_new_protected:Npn \__box_resize:N #1 + { + \__box_resize:NNN \l__box_right_new_dim + \l__box_scale_x_fp \l__box_right_dim + \__box_resize:NNN \l__box_bottom_new_dim + \l__box_scale_y_fp \l__box_bottom_dim + \__box_resize:NNN \l__box_top_new_dim + \l__box_scale_y_fp \l__box_top_dim + \__box_resize_common:N #1 + } +\cs_new_protected:Npn \__box_resize:NNN #1#2#3 + { + \dim_set:Nn #1 + { \fp_to_dim:n { \fp_abs:n { #2 } * \dim_to_fp:n { #3 } } } + } +\cs_new_protected:Npn \box_resize_to_ht:Nn #1#2 + { + \hbox_set:Nn #1 + { + \__box_resize_set_corners:N #1 + \fp_set:Nn \l__box_scale_y_fp + { + \dim_to_fp:n {#2} + / \dim_to_fp:n { \l__box_top_dim } + } + \fp_set_eq:NN \l__box_scale_x_fp \l__box_scale_y_fp + \__box_resize:N #1 + } + } +\cs_generate_variant:Nn \box_resize_to_ht:Nn { c } +\cs_new_protected:Npn \box_resize_to_ht_plus_dp:Nn #1#2 + { + \hbox_set:Nn #1 + { + \__box_resize_set_corners:N #1 + \fp_set:Nn \l__box_scale_y_fp + { + \dim_to_fp:n {#2} + / \dim_to_fp:n { \l__box_top_dim - \l__box_bottom_dim } + } + \fp_set_eq:NN \l__box_scale_x_fp \l__box_scale_y_fp + \__box_resize:N #1 + } + } +\cs_generate_variant:Nn \box_resize_to_ht_plus_dp:Nn { c } +\cs_new_protected:Npn \box_resize_to_wd:Nn #1#2 + { + \hbox_set:Nn #1 + { + \__box_resize_set_corners:N #1 + \fp_set:Nn \l__box_scale_x_fp + { \dim_to_fp:n {#2} / \dim_to_fp:n { \l__box_right_dim } } + \fp_set_eq:NN \l__box_scale_y_fp \l__box_scale_x_fp + \__box_resize:N #1 + } + } +\cs_generate_variant:Nn \box_resize_to_wd:Nn { c } +\cs_new_protected:Npn \box_resize_to_wd_and_ht:Nnn #1#2#3 + { + \hbox_set:Nn #1 + { + \__box_resize_set_corners:N #1 + \fp_set:Nn \l__box_scale_x_fp + { \dim_to_fp:n {#2} / \dim_to_fp:n { \l__box_right_dim } } + \fp_set:Nn \l__box_scale_y_fp + { + \dim_to_fp:n {#3} + / \dim_to_fp:n { \l__box_top_dim } + } + \__box_resize:N #1 + } + } +\cs_generate_variant:Nn \box_resize_to_wd_and_ht:Nnn { c } +\cs_new_protected:Npn \box_scale:Nnn #1#2#3 + { + \hbox_set:Nn #1 + { + \fp_set:Nn \l__box_scale_x_fp {#2} + \fp_set:Nn \l__box_scale_y_fp {#3} + \__box_scale_aux:N #1 + } + } +\cs_generate_variant:Nn \box_scale:Nnn { c } +\cs_new_protected:Npn \__box_scale_aux:N #1 + { + \dim_set:Nn \l__box_top_dim { \box_ht:N #1 } + \dim_set:Nn \l__box_bottom_dim { -\box_dp:N #1 } + \dim_set:Nn \l__box_right_dim { \box_wd:N #1 } + \dim_zero:N \l__box_left_dim + \dim_set:Nn \l__box_top_new_dim + { \fp_abs:n { \l__box_scale_y_fp } \l__box_top_dim } + \dim_set:Nn \l__box_bottom_new_dim + { \fp_abs:n { \l__box_scale_y_fp } \l__box_bottom_dim } + \dim_set:Nn \l__box_right_new_dim + { \fp_abs:n { \l__box_scale_x_fp } \l__box_right_dim } + \__box_resize_common:N #1 + } +\cs_new_protected:Npn \box_autosize_to_wd_and_ht:Nnn #1#2#3 + { \__box_autosize:Nnnn #1 {#2} {#3} { \box_ht:N #1 } } +\cs_generate_variant:Nn \box_autosize_to_wd_and_ht:Nnn { c } +\cs_new_protected:Npn \box_autosize_to_wd_and_ht_plus_dp:Nnn #1#2#3 + { \__box_autosize:Nnnn #1 {#2} {#3} { \box_ht:N #1 + \box_dp:N #1 } } +\cs_generate_variant:Nn \box_autosize_to_wd_and_ht_plus_dp:Nnn { c } +\cs_new_protected:Npn \__box_autosize:Nnnn #1#2#3#4 + { + \hbox_set:Nn #1 + { + \fp_set:Nn \l__box_scale_x_fp { ( #2 ) / \box_wd:N #1 } + \fp_set:Nn \l__box_scale_y_fp { ( #3 ) / ( #4 ) } + \fp_compare:nNnTF \l__box_scale_x_fp > \l__box_scale_y_fp + { \fp_set_eq:NN \l__box_scale_x_fp \l__box_scale_y_fp } + { \fp_set_eq:NN \l__box_scale_y_fp \l__box_scale_x_fp } + \__box_scale_aux:N #1 + } + } +\cs_new_protected:Npn \__box_resize_common:N #1 + { + \hbox_set:Nn \l__box_internal_box + { + \__driver_box_use_scale:Nnn + #1 + \l__box_scale_x_fp + \l__box_scale_y_fp + } + \fp_compare:nNnTF \l__box_scale_y_fp > \c_zero_fp + { + \box_set_ht:Nn \l__box_internal_box { \l__box_top_new_dim } + \box_set_dp:Nn \l__box_internal_box { -\l__box_bottom_new_dim } + } + { + \box_set_dp:Nn \l__box_internal_box { \l__box_top_new_dim } + \box_set_ht:Nn \l__box_internal_box { -\l__box_bottom_new_dim } + } + \fp_compare:nNnTF \l__box_scale_x_fp < \c_zero_fp + { + \hbox_to_wd:nn { \l__box_right_new_dim } + { + \tex_kern:D \l__box_right_new_dim + \box_use:N \l__box_internal_box + \tex_hss:D + } + } + { + \box_set_wd:Nn \l__box_internal_box { \l__box_right_new_dim } + \hbox:n + { + \tex_kern:D \c_zero_dim + \box_use:N \l__box_internal_box + \tex_hss:D + } + } + } +\cs_new_eq:NN \box_resize:Nnn \box_resize_to_wd_and_ht_plus_dp:Nnn +\cs_new_eq:NN \box_resize:cnn \box_resize_to_wd_and_ht_plus_dp:cnn %% File: l3coffins.dtx Copyright(C) 2010-2017 The LaTeX3 Project \box_new:N \l__coffin_internal_box \dim_new:N \l__coffin_internal_dim \tl_new:N \l__coffin_internal_tl \prop_new:N \c__coffin_corners_prop -\prop_put:Nnn \c__coffin_corners_prop { tl } { { 0 pt } { 0 pt } } -\prop_put:Nnn \c__coffin_corners_prop { tr } { { 0 pt } { 0 pt } } -\prop_put:Nnn \c__coffin_corners_prop { bl } { { 0 pt } { 0 pt } } -\prop_put:Nnn \c__coffin_corners_prop { br } { { 0 pt } { 0 pt } } +\prop_put:Nnn \c__coffin_corners_prop { tl } { { 0pt } { 0pt } } +\prop_put:Nnn \c__coffin_corners_prop { tr } { { 0pt } { 0pt } } +\prop_put:Nnn \c__coffin_corners_prop { bl } { { 0pt } { 0pt } } +\prop_put:Nnn \c__coffin_corners_prop { br } { { 0pt } { 0pt } } \prop_new:N \c__coffin_poles_prop -\tl_set:Nn \l__coffin_internal_tl { { 0 pt } { 0 pt } { 0 pt } { 1000 pt } } +\tl_set:Nn \l__coffin_internal_tl { { 0pt } { 0pt } { 0pt } { 1000pt } } \prop_put:Nno \c__coffin_poles_prop { l } { \l__coffin_internal_tl } \prop_put:Nno \c__coffin_poles_prop { hc } { \l__coffin_internal_tl } \prop_put:Nno \c__coffin_poles_prop { r } { \l__coffin_internal_tl } -\tl_set:Nn \l__coffin_internal_tl { { 0 pt } { 0 pt } { 1000 pt } { 0 pt } } +\tl_set:Nn \l__coffin_internal_tl { { 0pt } { 0pt } { 1000pt } { 0pt } } \prop_put:Nno \c__coffin_poles_prop { b } { \l__coffin_internal_tl } \prop_put:Nno \c__coffin_poles_prop { vc } { \l__coffin_internal_tl } \prop_put:Nno \c__coffin_poles_prop { t } { \l__coffin_internal_tl } @@ -16478,10 +16838,8 @@ { \hbox_set:Nn #1 { - \color_group_begin: - \color_ensure_current: - #2 - \color_group_end: + \color_ensure_current: + #2 } \__coffin_reset_structure:N #1 \__coffin_update_poles:N #1 @@ -16498,9 +16856,7 @@ \dim_set:Nn \tex_hsize:D {#2} \dim_set_eq:NN \linewidth \tex_hsize:D \dim_set_eq:NN \columnwidth \tex_hsize:D - \color_group_begin: - #3 - \color_group_end: + #3 } \__coffin_reset_structure:N #1 \__coffin_update_poles:N #1 @@ -16508,13 +16864,13 @@ \vbox_set_top:Nn \l__coffin_internal_box { \vbox_unpack:N #1 } \__coffin_set_pole:Nnx #1 { T } { - { 0 pt } + { 0pt } { \dim_eval:n { \box_ht:N #1 - \box_ht:N \l__coffin_internal_box } } - { 1000 pt } - { 0 pt } + { 1000pt } + { 0pt } } \box_clear:N \l__coffin_internal_box } @@ -16524,10 +16880,9 @@ { \__coffin_if_exist:NT #1 { - \hbox_set:Nw #1 \color_group_begin: \color_ensure_current: + \hbox_set:Nw #1 \color_ensure_current: \cs_set_protected:Npn \hcoffin_set_end: { - \color_group_end: \hbox_set_end: \__coffin_reset_structure:N #1 \__coffin_update_poles:N #1 @@ -16545,10 +16900,8 @@ \dim_set:Nn \tex_hsize:D {#2} \dim_set_eq:NN \linewidth \tex_hsize:D \dim_set_eq:NN \columnwidth \tex_hsize:D - \color_group_begin: \cs_set_protected:Npn \vcoffin_set_end: { - \color_group_end: \vbox_set_end: \__coffin_reset_structure:N #1 \__coffin_update_poles:N #1 @@ -16556,13 +16909,13 @@ \vbox_set_top:Nn \l__coffin_internal_box { \vbox_unpack:N #1 } \__coffin_set_pole:Nnx #1 { T } { - { 0 pt } + { 0pt } { \dim_eval:n { \box_ht:N #1 - \box_ht:N \l__coffin_internal_box } } - { 1000 pt } - { 0 pt } + { 1000pt } + { 0pt } } \box_clear:N \l__coffin_internal_box } @@ -16598,7 +16951,7 @@ { \__msg_kernel_error:nnxx { kernel } { unknown-coffin-pole } {#2} { \token_to_str:N #1 } - \tl_set:Nn #3 { { 0 pt } { 0 pt } { 0 pt } { 0 pt } } + \tl_set:Nn #3 { { 0pt } { 0pt } { 0pt } { 0pt } } } } \cs_new_protected:Npn \__coffin_reset_structure:N #1 @@ -16628,8 +16981,8 @@ { \__coffin_set_pole:Nnx #1 {#2} { - { 0 pt } { \dim_eval:n {#3} } - { 1000 pt } { 0 pt } + { 0pt } { \dim_eval:n {#3} } + { 1000pt } { 0pt } } } } @@ -16639,8 +16992,8 @@ { \__coffin_set_pole:Nnx #1 {#2} { - { \dim_eval:n {#3} } { 0 pt } - { 0 pt } { 1000 pt } + { \dim_eval:n {#3} } { 0pt } + { 0pt } { 1000pt } } } } @@ -16652,11 +17005,11 @@ \cs_new_protected:Npn \__coffin_update_corners:N #1 { \prop_put:cnx { l__coffin_corners_ \__int_value:w #1 _prop } { tl } - { { 0 pt } { \dim_eval:n { \box_ht:N #1 } } } + { { 0pt } { \dim_eval:n { \box_ht:N #1 } } } \prop_put:cnx { l__coffin_corners_ \__int_value:w #1 _prop } { tr } { { \dim_eval:n { \box_wd:N #1 } } { \dim_eval:n { \box_ht:N #1 } } } \prop_put:cnx { l__coffin_corners_ \__int_value:w #1 _prop } { bl } - { { 0 pt } { \dim_eval:n { - \box_dp:N #1 } } } + { { 0pt } { \dim_eval:n { -\box_dp:N #1 } } } \prop_put:cnx { l__coffin_corners_ \__int_value:w #1 _prop } { br } { { \dim_eval:n { \box_wd:N #1 } } { \dim_eval:n { -\box_dp:N #1 } } } } @@ -16665,33 +17018,33 @@ \prop_put:cnx { l__coffin_poles_ \__int_value:w #1 _prop } { hc } { { \dim_eval:n { 0.5 \box_wd:N #1 } } - { 0 pt } { 0 pt } { 1000 pt } + { 0pt } { 0pt } { 1000pt } } \prop_put:cnx { l__coffin_poles_ \__int_value:w #1 _prop } { r } { { \dim_eval:n { \box_wd:N #1 } } - { 0 pt } { 0 pt } { 1000 pt } + { 0pt } { 0pt } { 1000pt } } \prop_put:cnx { l__coffin_poles_ \__int_value:w #1 _prop } { vc } { - { 0 pt } + { 0pt } { \dim_eval:n { ( \box_ht:N #1 - \box_dp:N #1 ) / 2 } } - { 1000 pt } - { 0 pt } + { 1000pt } + { 0pt } } \prop_put:cnx { l__coffin_poles_ \__int_value:w #1 _prop } { t } { - { 0 pt } + { 0pt } { \dim_eval:n { \box_ht:N #1 } } - { 1000 pt } - { 0 pt } + { 1000pt } + { 0pt } } \prop_put:cnx { l__coffin_poles_ \__int_value:w #1 _prop } { b } { - { 0 pt } - { \dim_eval:n { - \box_dp:N #1 } } - { 1000 pt } - { 0 pt } + { 0pt } + { \dim_eval:n { -\box_dp:N #1 } } + { 1000pt } + { 0pt } } } \cs_new_protected:Npn \__coffin_calculate_intersection:Nnn #1#2#3 @@ -16816,21 +17169,21 @@ { \tex_kern:D -\l__coffin_internal_dim } } \__coffin_reset_structure:N \l__coffin_aligned_coffin - \prop_clear:c - { l__coffin_corners_ \__int_value:w \l__coffin_aligned_coffin _ prop } - \__coffin_update_poles:N \l__coffin_aligned_coffin + \prop_clear:c + { l__coffin_corners_ \__int_value:w \l__coffin_aligned_coffin _ prop } + \__coffin_update_poles:N \l__coffin_aligned_coffin \dim_compare:nNnTF \l__coffin_offset_x_dim < \c_zero_dim { - \__coffin_offset_poles:Nnn #1 { -\l__coffin_offset_x_dim } { 0 pt } - \__coffin_offset_poles:Nnn #4 { 0 pt } { \l__coffin_offset_y_dim } - \__coffin_offset_corners:Nnn #1 { -\l__coffin_offset_x_dim } { 0 pt } - \__coffin_offset_corners:Nnn #4 { 0 pt } { \l__coffin_offset_y_dim } + \__coffin_offset_poles:Nnn #1 { -\l__coffin_offset_x_dim } { 0pt } + \__coffin_offset_poles:Nnn #4 { 0pt } { \l__coffin_offset_y_dim } + \__coffin_offset_corners:Nnn #1 { -\l__coffin_offset_x_dim } { 0pt } + \__coffin_offset_corners:Nnn #4 { 0pt } { \l__coffin_offset_y_dim } } { - \__coffin_offset_poles:Nnn #1 { 0 pt } { 0 pt } + \__coffin_offset_poles:Nnn #1 { 0pt } { 0pt } \__coffin_offset_poles:Nnn #4 { \l__coffin_offset_x_dim } { \l__coffin_offset_y_dim } - \__coffin_offset_corners:Nnn #1 { 0 pt } { 0 pt } + \__coffin_offset_corners:Nnn #1 { 0pt } { 0pt } \__coffin_offset_corners:Nnn #4 { \l__coffin_offset_x_dim } { \l__coffin_offset_y_dim } } @@ -16850,7 +17203,7 @@ { l__coffin_corners_ \__int_value:w \l__coffin_aligned_coffin _prop } { l__coffin_corners_ \__int_value:w #1 _prop } \__coffin_update_poles:N \l__coffin_aligned_coffin - \__coffin_offset_poles:Nnn #1 { 0 pt } { 0 pt } + \__coffin_offset_poles:Nnn #1 { 0pt } { 0pt } \__coffin_offset_poles:Nnn #4 { \l__coffin_offset_x_dim } { \l__coffin_offset_y_dim } \__coffin_update_vertical_poles:NNN #1 #4 \l__coffin_aligned_coffin @@ -16935,11 +17288,11 @@ \dim_compare:nNnTF {#2} < {#6} { \__coffin_set_pole:Nnx #9 { T } - { { 0 pt } {#6} { 1000 pt } { 0 pt } } + { { 0pt } {#6} { 1000pt } { 0pt } } } { \__coffin_set_pole:Nnx #9 { T } - { { 0 pt } {#2} { 1000 pt } { 0 pt } } + { { 0pt } {#2} { 1000pt } { 0pt } } } } \cs_new_protected:Npn \__coffin_update_B:nnnnnnnnN #1#2#3#4#5#6#7#8#9 @@ -16947,11 +17300,11 @@ \dim_compare:nNnTF {#2} < {#6} { \__coffin_set_pole:Nnx #9 { B } - { { 0 pt } {#2} { 1000 pt } { 0 pt } } + { { 0pt } {#2} { 1000pt } { 0pt } } } { \__coffin_set_pole:Nnx #9 { B } - { { 0 pt } {#6} { 1000 pt } { 0 pt } } + { { 0pt } {#6} { 1000pt } { 0pt } } } } \cs_new_protected:Npn \coffin_typeset:Nnnnn #1#2#3#4#5 @@ -17003,7 +17356,7 @@ \prop_put:Nnn \l__coffin_display_handles_prop { Br } { { b } { l } { 1 } { -1 } } \dim_new:N \l__coffin_display_offset_dim -\dim_set:Nn \l__coffin_display_offset_dim { 2 pt } +\dim_set:Nn \l__coffin_display_offset_dim { 2pt } \dim_new:N \l__coffin_display_x_dim \dim_new:N \l__coffin_display_y_dim \prop_new:N \l__coffin_display_poles_prop @@ -17014,10 +17367,10 @@ \hcoffin_set:Nn \l__coffin_display_pole_coffin { \color {#4} - \rule { 1 pt } { 1 pt } + \rule { 1pt } { 1pt } } \coffin_attach_mark:NnnNnnnn #1 {#2} {#3} - \l__coffin_display_pole_coffin { hc } { vc } { 0 pt } { 0 pt } + \l__coffin_display_pole_coffin { hc } { vc } { 0pt } { 0pt } \hcoffin_set:Nn \l__coffin_display_coord_coffin { \color {#4} @@ -17034,7 +17387,7 @@ { \coffin_attach_mark:NnnNnnnn #1 {#2} {#3} \l__coffin_display_coord_coffin { l } { vc } - { 1 pt } { 0 pt } + { 1pt } { 0pt } } { \exp_last_unbraced:No \__coffin_mark_handle_aux:nnnnNnn @@ -17059,7 +17412,7 @@ \hcoffin_set:Nn \l__coffin_display_pole_coffin { \color {#2} - \rule { 1 pt } { 1 pt } + \rule { 1pt } { 1pt } } \prop_set_eq:Nc \l__coffin_display_poles_prop { l__coffin_poles_ \__int_value:w #1 _prop } @@ -17090,7 +17443,7 @@ \dim_set:Nn \l__coffin_display_y_dim { \l__coffin_y_dim } \__coffin_display_attach:Nnnnn \l__coffin_display_pole_coffin { hc } { vc } - { 0 pt } { 0 pt } + { 0pt } { 0pt } \hcoffin_set:Nn \l__coffin_display_coord_coffin { \color {#6} @@ -17107,7 +17460,7 @@ { \__coffin_display_attach:Nnnnn \l__coffin_display_coord_coffin { l } { vc } - { 1 pt } { 0 pt } + { 1pt } { 0pt } } { \exp_last_unbraced:No @@ -17205,25 +17558,11 @@ \cs_new_eq:NN \color_group_begin: \group_begin: \cs_new_protected:Npn \color_group_end: { - \tex_par:D + \par \group_end: } -\cs_new_protected:Npn \color_ensure_current: { } -\AtBeginDocument - { - \cs_if_exist:NTF \__driver_color_ensure_current: - { - \cs_set_protected:Npn \color_ensure_current: - { \__driver_color_ensure_current: } - } - { - \cs_if_exist:NT \set@color - { - \cs_set_protected:Npn \color_ensure_current: - { \set@color } - } - } - } +\cs_new_protected:Npn \color_ensure_current: + { \__driver_color_ensure_current: } %% File: l3sys.dtx Copyright (C) 2015-2017 The LaTeX3 Project \str_const:Nx \c_sys_jobname_str { \tex_jobname:D } \int_const:Nn \c_sys_minute_int @@ -17258,11 +17597,9 @@ } \cs_if_exist:NT \ptex_kanjiskip:D { - \bool_if:nTF - { - \cs_if_exist_p:N \uptex_disablecjktoken:D && - \int_compare_p:nNn { \ptex_jis:D "2121 } = { "3000 } - } + \bool_lazy_and:nnTF + { \cs_if_exist_p:N \uptex_disablecjktoken:D } + { \int_compare_p:nNn { \ptex_jis:D "2121 } = { "3000 } } { \cs_gset_eq:NN \sys_if_engine_uptex:T \use:n \cs_gset_eq:NN \sys_if_engine_uptex:F \use_none:n @@ -17359,6 +17696,8 @@ \__deprecation_error:Nnn \tl_to_lowercase:n { } { 2017-12-31 } \__deprecation_error:Nnn \tl_to_uppercase:n { } { 2017-12-31 } \__deprecation_error:Nnn \ior_get_str:NN { \ior_str_get:NN } { 2017-12-31 } + \__deprecation_error:Nnn \box_resize:Nnn { \box_resize_to_wd_and_ht_plus_dp:Nnn } { 2018-12-31 } + \__deprecation_error:Nnn \box_resize:cnn { \box_resize_to_wd_and_ht_plus_dp:cnn } { 2018-12-31 } \__deprecation_error:Nnn \c_minus_one { - 1 } { 2018-12-31 } \__deprecation_error:Nnn \sort_ordered: { \sort_return_same: } { 2018-12-31 } \__deprecation_error:Nnn \sort_reversed: { \sort_return_swapped: } { 2018-12-31 } @@ -17366,297 +17705,6 @@ \cs_set_eq:NN \deprecation_error: \scan_stop: } %% File: l3candidates.dtx Copyright (C) 2012-2017 The LaTeX3 Project -\fp_new:N \l__box_angle_fp -\fp_new:N \l__box_cos_fp -\fp_new:N \l__box_sin_fp -\dim_new:N \l__box_top_dim -\dim_new:N \l__box_bottom_dim -\dim_new:N \l__box_left_dim -\dim_new:N \l__box_right_dim -\dim_new:N \l__box_top_new_dim -\dim_new:N \l__box_bottom_new_dim -\dim_new:N \l__box_left_new_dim -\dim_new:N \l__box_right_new_dim -\box_new:N \l__box_internal_box -\cs_new_protected:Npn \box_rotate:Nn #1#2 - { - \hbox_set:Nn #1 - { - \group_begin: - \fp_set:Nn \l__box_angle_fp {#2} - \fp_set:Nn \l__box_sin_fp { sind ( \l__box_angle_fp ) } - \fp_set:Nn \l__box_cos_fp { cosd ( \l__box_angle_fp ) } - \__box_rotate:N #1 - \group_end: - } - } -\cs_new_protected:Npn \__box_rotate:N #1 - { - \dim_set:Nn \l__box_top_dim { \box_ht:N #1 } - \dim_set:Nn \l__box_bottom_dim { -\box_dp:N #1 } - \dim_set:Nn \l__box_right_dim { \box_wd:N #1 } - \dim_zero:N \l__box_left_dim - \fp_compare:nNnTF \l__box_sin_fp > \c_zero_fp - { - \fp_compare:nNnTF \l__box_cos_fp > \c_zero_fp - { \__box_rotate_quadrant_one: } - { \__box_rotate_quadrant_two: } - } - { - \fp_compare:nNnTF \l__box_cos_fp < \c_zero_fp - { \__box_rotate_quadrant_three: } - { \__box_rotate_quadrant_four: } - } - \hbox_set:Nn \l__box_internal_box { \box_use:N #1 } - \hbox_set:Nn \l__box_internal_box - { - \tex_kern:D -\l__box_left_new_dim - \hbox:n - { - \__driver_box_use_rotate:Nn - \l__box_internal_box - \l__box_angle_fp - } - } - \box_set_ht:Nn \l__box_internal_box { \l__box_top_new_dim } - \box_set_dp:Nn \l__box_internal_box { -\l__box_bottom_new_dim } - \box_set_wd:Nn \l__box_internal_box - { \l__box_right_new_dim - \l__box_left_new_dim } - \box_use:N \l__box_internal_box - } -\cs_new_protected:Npn \__box_rotate_x:nnN #1#2#3 - { - \dim_set:Nn #3 - { - \fp_to_dim:n - { - \l__box_cos_fp * \dim_to_fp:n {#1} - - \l__box_sin_fp * \dim_to_fp:n {#2} - } - } - } -\cs_new_protected:Npn \__box_rotate_y:nnN #1#2#3 - { - \dim_set:Nn #3 - { - \fp_to_dim:n - { - \l__box_sin_fp * \dim_to_fp:n {#1} - + \l__box_cos_fp * \dim_to_fp:n {#2} - } - } - } -\cs_new_protected:Npn \__box_rotate_quadrant_one: - { - \__box_rotate_y:nnN \l__box_right_dim \l__box_top_dim - \l__box_top_new_dim - \__box_rotate_y:nnN \l__box_left_dim \l__box_bottom_dim - \l__box_bottom_new_dim - \__box_rotate_x:nnN \l__box_left_dim \l__box_top_dim - \l__box_left_new_dim - \__box_rotate_x:nnN \l__box_right_dim \l__box_bottom_dim - \l__box_right_new_dim - } -\cs_new_protected:Npn \__box_rotate_quadrant_two: - { - \__box_rotate_y:nnN \l__box_right_dim \l__box_bottom_dim - \l__box_top_new_dim - \__box_rotate_y:nnN \l__box_left_dim \l__box_top_dim - \l__box_bottom_new_dim - \__box_rotate_x:nnN \l__box_right_dim \l__box_top_dim - \l__box_left_new_dim - \__box_rotate_x:nnN \l__box_left_dim \l__box_bottom_dim - \l__box_right_new_dim - } -\cs_new_protected:Npn \__box_rotate_quadrant_three: - { - \__box_rotate_y:nnN \l__box_left_dim \l__box_bottom_dim - \l__box_top_new_dim - \__box_rotate_y:nnN \l__box_right_dim \l__box_top_dim - \l__box_bottom_new_dim - \__box_rotate_x:nnN \l__box_right_dim \l__box_bottom_dim - \l__box_left_new_dim - \__box_rotate_x:nnN \l__box_left_dim \l__box_top_dim - \l__box_right_new_dim - } -\cs_new_protected:Npn \__box_rotate_quadrant_four: - { - \__box_rotate_y:nnN \l__box_left_dim \l__box_top_dim - \l__box_top_new_dim - \__box_rotate_y:nnN \l__box_right_dim \l__box_bottom_dim - \l__box_bottom_new_dim - \__box_rotate_x:nnN \l__box_left_dim \l__box_bottom_dim - \l__box_left_new_dim - \__box_rotate_x:nnN \l__box_right_dim \l__box_top_dim - \l__box_right_new_dim - } -\fp_new:N \l__box_scale_x_fp -\fp_new:N \l__box_scale_y_fp -\cs_new_protected:Npn \box_resize:Nnn #1#2#3 - { - \hbox_set:Nn #1 - { - \group_begin: - \__box_resize_set_corners:N #1 - \fp_set:Nn \l__box_scale_x_fp - { \dim_to_fp:n {#2} / \dim_to_fp:n { \l__box_right_dim } } - \fp_set:Nn \l__box_scale_y_fp - { - \dim_to_fp:n {#3} - / \dim_to_fp:n { \l__box_top_dim - \l__box_bottom_dim } - } - \__box_resize:N #1 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize:Nnn { c } -\cs_new_protected:Npn \__box_resize_set_corners:N #1 - { - \dim_set:Nn \l__box_top_dim { \box_ht:N #1 } - \dim_set:Nn \l__box_bottom_dim { -\box_dp:N #1 } - \dim_set:Nn \l__box_right_dim { \box_wd:N #1 } - \dim_zero:N \l__box_left_dim - } -\cs_new_protected:Npn \__box_resize:N #1 - { - \__box_resize:NNN \l__box_right_new_dim - \l__box_scale_x_fp \l__box_right_dim - \__box_resize:NNN \l__box_bottom_new_dim - \l__box_scale_y_fp \l__box_bottom_dim - \__box_resize:NNN \l__box_top_new_dim - \l__box_scale_y_fp \l__box_top_dim - \__box_resize_common:N #1 - } -\cs_new_protected:Npn \__box_resize:NNN #1#2#3 - { - \dim_set:Nn #1 - { \fp_to_dim:n { \fp_abs:n { #2 } * \dim_to_fp:n { #3 } } } - } -\cs_new_protected:Npn \box_resize_to_ht:Nn #1#2 - { - \hbox_set:Nn #1 - { - \group_begin: - \__box_resize_set_corners:N #1 - \fp_set:Nn \l__box_scale_y_fp - { - \dim_to_fp:n {#2} - / \dim_to_fp:n { \l__box_top_dim } - } - \fp_set_eq:NN \l__box_scale_x_fp \l__box_scale_y_fp - \__box_resize:N #1 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize_to_ht:Nn { c } -\cs_new_protected:Npn \box_resize_to_ht_plus_dp:Nn #1#2 - { - \hbox_set:Nn #1 - { - \group_begin: - \__box_resize_set_corners:N #1 - \fp_set:Nn \l__box_scale_y_fp - { - \dim_to_fp:n {#2} - / \dim_to_fp:n { \l__box_top_dim - \l__box_bottom_dim } - } - \fp_set_eq:NN \l__box_scale_x_fp \l__box_scale_y_fp - \__box_resize:N #1 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize_to_ht_plus_dp:Nn { c } -\cs_new_protected:Npn \box_resize_to_wd:Nn #1#2 - { - \hbox_set:Nn #1 - { - \group_begin: - \__box_resize_set_corners:N #1 - \fp_set:Nn \l__box_scale_x_fp - { \dim_to_fp:n {#2} / \dim_to_fp:n { \l__box_right_dim } } - \fp_set_eq:NN \l__box_scale_y_fp \l__box_scale_x_fp - \__box_resize:N #1 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize_to_wd:Nn { c } -\cs_new_protected:Npn \box_resize_to_wd_and_ht:Nnn #1#2#3 - { - \hbox_set:Nn #1 - { - \group_begin: - \__box_resize_set_corners:N #1 - \fp_set:Nn \l__box_scale_x_fp - { \dim_to_fp:n {#2} / \dim_to_fp:n { \l__box_right_dim } } - \fp_set:Nn \l__box_scale_y_fp - { - \dim_to_fp:n {#3} - / \dim_to_fp:n { \l__box_top_dim } - } - \__box_resize:N #1 - \group_end: - } - } -\cs_generate_variant:Nn \box_resize_to_wd_and_ht:Nnn { c } -\cs_new_protected:Npn \box_scale:Nnn #1#2#3 - { - \hbox_set:Nn #1 - { - \group_begin: - \fp_set:Nn \l__box_scale_x_fp {#2} - \fp_set:Nn \l__box_scale_y_fp {#3} - \dim_set:Nn \l__box_top_dim { \box_ht:N #1 } - \dim_set:Nn \l__box_bottom_dim { -\box_dp:N #1 } - \dim_set:Nn \l__box_right_dim { \box_wd:N #1 } - \dim_zero:N \l__box_left_dim - \dim_set:Nn \l__box_top_new_dim - { \fp_abs:n { \l__box_scale_y_fp } \l__box_top_dim } - \dim_set:Nn \l__box_bottom_new_dim - { \fp_abs:n { \l__box_scale_y_fp } \l__box_bottom_dim } - \dim_set:Nn \l__box_right_new_dim - { \fp_abs:n { \l__box_scale_x_fp } \l__box_right_dim } - \__box_resize_common:N #1 - \group_end: - } - } -\cs_generate_variant:Nn \box_scale:Nnn { c } -\cs_new_protected:Npn \__box_resize_common:N #1 - { - \hbox_set:Nn \l__box_internal_box - { - \__driver_box_use_scale:Nnn - #1 - \l__box_scale_x_fp - \l__box_scale_y_fp - } - \fp_compare:nNnTF \l__box_scale_y_fp > \c_zero_fp - { - \box_set_ht:Nn \l__box_internal_box { \l__box_top_new_dim } - \box_set_dp:Nn \l__box_internal_box { -\l__box_bottom_new_dim } - } - { - \box_set_dp:Nn \l__box_internal_box { \l__box_top_new_dim } - \box_set_ht:Nn \l__box_internal_box { -\l__box_bottom_new_dim } - } - \fp_compare:nNnTF \l__box_scale_x_fp < \c_zero_fp - { - \hbox_to_wd:nn { \l__box_right_new_dim } - { - \tex_kern:D \l__box_right_new_dim - \box_use:N \l__box_internal_box - \tex_hss:D - } - } - { - \box_set_wd:Nn \l__box_internal_box { \l__box_right_new_dim } - \hbox:n - { - \tex_kern:D \c_zero_dim - \box_use:N \l__box_internal_box - \tex_hss:D - } - } - } \cs_new_protected:Npn \box_clip:N #1 { \hbox_set:Nn #1 { \__driver_box_use_clip:N #1 } } \cs_generate_variant:Nn \box_clip:N { c } @@ -17925,7 +17973,7 @@ \dim_to_fp:n {#3} / \dim_to_fp:n { \coffin_ht:N #1 + \coffin_dp:N #1 } } - \box_resize:Nnn #1 {#2} {#3} + \box_resize_to_wd_and_ht_plus_dp:Nnn #1 {#2} {#3} \__coffin_resize_common:Nnn #1 {#2} {#3} } \cs_generate_variant:Nn \coffin_resize:Nnn { c } @@ -18037,7 +18085,7 @@ } \cs_new_protected:Npn \__ior_map_inline:NNNn #1#2#3#4 { - \cs_set:Npn #1 ##1 {#4} + \cs_gset_protected:Npn #1 ##1 {#4} \ior_if_eof:NF #3 { \__ior_map_inline_loop:NNN #1#2#3 } \__prg_break_point:Nn \ior_map_break: { \int_gdecr:N \g__prg_map_int } @@ -18245,6 +18293,18 @@ #2 } } +\cs_if_exist:NTF \pdftex_uniformdeviate:D + { + \prg_new_conditional:Npnn \sys_if_rand_exist: { p , T , F , TF } + { \prg_return_true: } + } + { + \prg_new_conditional:Npnn \sys_if_rand_exist: { p , T , F , TF } + { \prg_return_false: } + } +\cs_new:Npn \sys_rand_seed: { \tex_the:D \pdftex_randomseed:D } +\cs_new_protected:Npn \sys_gset_rand_seed:n #1 + { \pdftex_setrandomseed:D \__int_eval:w #1 \__int_eval_end: } \prg_new_conditional:Npnn \tl_if_single_token:n #1 { p , T , F , TF } { \tl_if_head_is_N_type:nTF {#1} @@ -18934,10 +18994,9 @@ \__tl_tmp:w \c__unicode_I_ogonek_tl { 012E } \group_end: \group_begin: - \bool_if:nT - { - \sys_if_engine_pdftex_p: || \sys_if_engine_uptex_p: - } + \bool_lazy_or:nnT + { \sys_if_engine_pdftex_p: } + { \sys_if_engine_uptex_p: } { \cs_set_protected:Npn \__tl_loop:nn #1#2 { diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex b/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex index d219cea798d..7ff0bc2bb26 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex +++ b/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex @@ -19,7 +19,7 @@ %% and all files in that bundle must be distributed together. %% %% File: expl3.dtx Copyright (C) 1990-2017 The LaTeX3 Project -\def\ExplFileDate{2017/04/01}% +\def\ExplFileDate{2017/05/13}% \let\ExplLoaderFileDate\ExplFileDate \begingroup \def\tempa{LaTeX2e}% @@ -73,7 +73,6 @@ \expandafter\endinput \fi \cs_set_eq:NN \__iow_wrap_set:Nx \tl_set:Nx -\protected\def\GetIdInfoLog{} \cs_set_protected:Npn \ProvidesExplFile { \group_begin: diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3.sty b/Master/texmf-dist/tex/latex/l3kernel/expl3.sty index b72e6e3ac4b..ffdcd396e0b 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/expl3.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/expl3.sty @@ -19,7 +19,7 @@ %% and all files in that bundle must be distributed together. %% %% File: expl3.dtx Copyright (C) 1990-2017 The LaTeX3 Project -\def\ExplFileDate{2017/04/01}% +\def\ExplFileDate{2017/05/13}% \let\ExplLoaderFileDate\ExplFileDate \ProvidesPackage{expl3} [% @@ -95,11 +95,9 @@ \sys_if_output_pdf:TF { pdfmode } { - \bool_if:nTF - { - \sys_if_engine_pdftex_p: || - \sys_if_engine_luatex_p: - } + \bool_lazy_or:nnTF + { \sys_if_engine_pdftex_p: } + { \sys_if_engine_luatex_p: } { dvips } { dvipdfmx } } @@ -226,7 +224,7 @@ } \cs_set_protected:Npn \box_rotate:Nn #1#2 { \hbox_set:Nn #1 { \rotatebox {#2} { \box_use:N #1 } } } - \cs_set_protected:Npn \box_resize:Nnn #1#2#3 + \cs_set_protected:Npn \box_resize_to_wd_and_ht_plus_dp:Nnn #1#2#3 { \hbox_set:Nn #1 { @@ -252,15 +250,13 @@ { \box_use:N #1 } } } - \cs_set_protected:Npn \box_scale:Nnn #1#2#3 + \cs_set_protected:Npn \__box_scale_aux:N #1 { - \hbox_set:Nn #1 - { - \exp_last_unbraced:Nx \scalebox - { { \fp_eval:n {#2} } [ \fp_eval:n {#3} ] } - { \box_use:N #1 } - } + \exp_last_unbraced:Nx \scalebox + { { \fp_use:N \l__box_scale_x_fp } [ \fp_use:N \l__box_scale_y_fp ] } + { \box_use:N #1 } } + \cs_set_protected:Npn \color_ensure_current: { \set@color } } { \group_begin: diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3basics.sty b/Master/texmf-dist/tex/latex/l3kernel/l3basics.sty index ecc4ec63d8b..01247fc3cc7 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3basics.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3basics.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3basics.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3bootstrap.sty b/Master/texmf-dist/tex/latex/l3kernel/l3bootstrap.sty index 5802b76351d..10179692ae8 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3bootstrap.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3bootstrap.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3bootstrap.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3box.sty b/Master/texmf-dist/tex/latex/l3kernel/l3box.sty index e97f3c82e8a..772f216bda4 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3box.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3box.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3box.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3candidates.sty b/Master/texmf-dist/tex/latex/l3kernel/l3candidates.sty index 3e9cc1ca2a0..b285554a278 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3candidates.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3candidates.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3candidates.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3clist.sty b/Master/texmf-dist/tex/latex/l3kernel/l3clist.sty index 448c5e6416c..398a0a2c985 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3clist.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3clist.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3clist.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3coffins.sty b/Master/texmf-dist/tex/latex/l3kernel/l3coffins.sty index 8402a41fea2..ec1a9cc35b5 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3coffins.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3coffins.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3coffins.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3color.sty b/Master/texmf-dist/tex/latex/l3kernel/l3color.sty index b40efec230e..61cbb081a93 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3color.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3color.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3color.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3doc.cls b/Master/texmf-dist/tex/latex/l3kernel/l3doc.cls index 7282e860ae8..87a276fbd8b 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3doc.cls +++ b/Master/texmf-dist/tex/latex/l3kernel/l3doc.cls @@ -20,7 +20,7 @@ %% %% File: l3doc.dtx Copyright (C) 1990-2017 The LaTeX3 project \RequirePackage{expl3,xparse,calc} -\ProvidesExplClass{l3doc}{2017/04/01}{} +\ProvidesExplClass{l3doc}{2017/05/13}{} {L3 Experimental documentation class} \clist_new:N \g_docinput_clist \seq_new:N \g_doc_functions_seq @@ -892,7 +892,7 @@ \clist_clear:N \l__codedoc_function_label_clist \tl_set:Nn \l__codedoc_override_module_tl { \q_no_value } \char_set_catcode_active:N \< - \cs_set_protected:Npn < ##1 > { \meta {##1} } + \cs_set_protected_nopar:Npn < ##1 > { \meta {##1} } } \group_end: \cs_new_protected:Npn \__codedoc_function_reset: diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3dvipdfmx.def b/Master/texmf-dist/tex/latex/l3kernel/l3dvipdfmx.def index 421757e959a..a2e1fb7ee87 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3dvipdfmx.def +++ b/Master/texmf-dist/tex/latex/l3kernel/l3dvipdfmx.def @@ -25,26 +25,9 @@ \cs_new_protected:Npn \__driver_literal:n #1 { \tex_special:D { pdf:literal~ #1 } } \cs_new_protected:Npn \__driver_scope_begin: - { \__driver_literal:n { q } } + { \tex_special:D { x:gsave } } \cs_new_protected:Npn \__driver_scope_end: - { \__driver_literal:n { Q } } -\cs_new_protected:Npn \__driver_matrix:n #1 - { \__driver_literal:n { #1 \c_space_tl 0~0~cm } } -\tl_new:N \l__driver_current_color_tl -\tl_set:Nn \l__driver_current_color_tl { [ 0 ] } -\AtBeginDocument - { - \@ifpackageloaded { color } - { \tl_set:Nn \l__driver_current_color_tl { \current@color } } - { } - } -\cs_new_protected:Npn \__driver_color_ensure_current: - { - \tex_special:D { pdf:bcolor~\l__driver_current_color_tl } - \group_insert_after:N \__driver_color_reset: - } -\cs_new_protected:Npn \__driver_color_reset: - { \tex_special:D { pdf:ecolor } } + { \tex_special:D { x:grestore } } \cs_new_protected:Npn \__driver_box_use_clip:N #1 { \__driver_scope_begin: @@ -63,41 +46,43 @@ \cs_new_protected:Npn \__driver_box_use_rotate:Nn #1#2 { \__driver_scope_begin: - \box_set_wd:Nn #1 \c_zero_dim - \fp_set:Nn \l__driver_cos_fp { round ( cosd ( #2 ) , 5 ) } - \fp_compare:nNnT \l__driver_cos_fp = \c_zero_fp - { \fp_zero:N \l__driver_cos_fp } - \fp_set:Nn \l__driver_sin_fp { round ( sind ( #2 ) , 5 ) } - \__driver_matrix:n + \tex_special:D { - \fp_use:N \l__driver_cos_fp \c_space_tl - \fp_compare:nNnTF \l__driver_sin_fp = \c_zero_fp - { 0~0 } - { - \fp_use:N \l__driver_sin_fp - \c_space_tl - \fp_eval:n { -\l__driver_sin_fp } - } - \c_space_tl - \fp_use:N \l__driver_cos_fp + x:rotate~ + \fp_compare:nNnTF {#2} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( #2 , 5 ) } } } - \box_use:N #1 - \__driver_scope_end: + \box_use:N #1 + \__driver_scope_end: } -\fp_new:N \l__driver_cos_fp -\fp_new:N \l__driver_sin_fp \cs_new_protected:Npn \__driver_box_use_scale:Nnn #1#2#3 { \__driver_scope_begin: - \__driver_matrix:n + \tex_special:D { + x:scale~ \fp_eval:n { round ( #2 , 5 ) } ~ - 0~0~ \fp_eval:n { round ( #3 , 5 ) } } \hbox_overlap_right:n { \box_use:N #1 } \__driver_scope_end: } +\tl_new:N \l__driver_current_color_tl +\tl_set:Nn \l__driver_current_color_tl { [ 0 ] } +\AtBeginDocument + { + \@ifpackageloaded { color } + { \tl_set:Nn \l__driver_current_color_tl { \current@color } } + { } + } +\cs_new_protected:Npn \__driver_color_ensure_current: + { + \tex_special:D { pdf:bcolor~\l__driver_current_color_tl } + \group_insert_after:N \__driver_color_reset: + } +\cs_new_protected:Npn \__driver_color_reset: + { \tex_special:D { pdf:ecolor } } \cs_new_eq:NN \__driver_draw_literal:n \__driver_literal:n \cs_generate_variant:Nn \__driver_draw_literal:n { x } \cs_new_protected:Npn \__driver_draw_begin: diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3expan.sty b/Master/texmf-dist/tex/latex/l3kernel/l3expan.sty index 1384b917ae2..d359460c6a9 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3expan.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3expan.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3expan.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3file.sty b/Master/texmf-dist/tex/latex/l3kernel/l3file.sty index 1d304be09b0..e3885146b5b 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3file.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3file.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3file.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3fp.sty b/Master/texmf-dist/tex/latex/l3kernel/l3fp.sty index b0db3df4086..25d5f463f93 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3fp.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3fp.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3fp.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3int.sty b/Master/texmf-dist/tex/latex/l3kernel/l3int.sty index 39f59525ccd..2cf8d17adaf 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3int.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3int.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3int.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3keys.sty b/Master/texmf-dist/tex/latex/l3kernel/l3keys.sty index 6bf04e91edf..f70076e7624 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3keys.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3keys.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3keys.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3msg.sty b/Master/texmf-dist/tex/latex/l3kernel/l3msg.sty index 5f56f117b47..a69bed4d629 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3msg.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3msg.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3msg.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3names.sty b/Master/texmf-dist/tex/latex/l3kernel/l3names.sty index d3ed998a594..70dfa8a8f9e 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3names.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3names.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3names.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3pdfmode.def b/Master/texmf-dist/tex/latex/l3kernel/l3pdfmode.def index c4e02851cbd..aa41c1f1c1b 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3pdfmode.def +++ b/Master/texmf-dist/tex/latex/l3kernel/l3pdfmode.def @@ -48,31 +48,6 @@ { \pdftex_pdfsetmatrix:D } {#1} } -\tl_new:N \l__driver_current_color_tl -\tl_set:Nn \l__driver_current_color_tl { 0~g~0~G } -\AtBeginDocument - { - \@ifpackageloaded { color } - { \tl_set:Nn \l__driver_current_color_tl { \current@color } } - { } - } -\int_new:N \l__driver_color_stack_int -\cs_new_protected:Npx \__driver_color_ensure_current: - { - \cs_if_exist:NTF \luatex_pdfextension:D - { \luatex_pdfextension:D colorstack } - { \pdftex_pdfcolorstack:D } - \exp_not:N \l__driver_color_stack_int push - { \exp_not:N \l__driver_current_color_tl } - \group_insert_after:N \exp_not:N \__driver_color_reset: - } -\cs_new_protected:Npx \__driver_color_reset: - { - \cs_if_exist:NTF \luatex_pdfextension:D - { \luatex_pdfextension:D colorstack } - { \pdftex_pdfcolorstack:D } - \exp_not:N \l__driver_color_stack_int pop \scan_stop: - } \cs_new_protected:Npn \__driver_box_use_clip:N #1 { \__driver_scope_begin: @@ -126,6 +101,31 @@ \hbox_overlap_right:n { \box_use:N #1 } \__driver_scope_end: } +\tl_new:N \l__driver_current_color_tl +\tl_set:Nn \l__driver_current_color_tl { 0~g~0~G } +\AtBeginDocument + { + \@ifpackageloaded { color } + { \tl_set:Nn \l__driver_current_color_tl { \current@color } } + { } + } +\int_new:N \l__driver_color_stack_int +\cs_new_protected:Npx \__driver_color_ensure_current: + { + \cs_if_exist:NTF \luatex_pdfextension:D + { \luatex_pdfextension:D colorstack } + { \pdftex_pdfcolorstack:D } + \exp_not:N \l__driver_color_stack_int push + { \exp_not:N \l__driver_current_color_tl } + \group_insert_after:N \exp_not:N \__driver_color_reset: + } +\cs_new_protected:Npx \__driver_color_reset: + { + \cs_if_exist:NTF \luatex_pdfextension:D + { \luatex_pdfextension:D colorstack } + { \pdftex_pdfcolorstack:D } + \exp_not:N \l__driver_color_stack_int pop \scan_stop: + } \cs_new_eq:NN \__driver_draw_literal:n \__driver_literal:n \cs_generate_variant:Nn \__driver_draw_literal:n { x } \cs_new_protected:Npn \__driver_draw_begin: diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3prg.sty b/Master/texmf-dist/tex/latex/l3kernel/l3prg.sty index a17d2ea2240..0dd86d4d6fa 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3prg.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3prg.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3prg.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3prop.sty b/Master/texmf-dist/tex/latex/l3kernel/l3prop.sty index 77f6d1baa0e..ee0bec1c87e 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3prop.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3prop.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3prop.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3quark.sty b/Master/texmf-dist/tex/latex/l3kernel/l3quark.sty index 11fb023c9f8..40673cd62b0 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3quark.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3quark.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3quark.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3seq.sty b/Master/texmf-dist/tex/latex/l3kernel/l3seq.sty index a37f41ed175..dbd89d0a301 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3seq.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3seq.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3seq.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3skip.sty b/Master/texmf-dist/tex/latex/l3kernel/l3skip.sty index 0ecd47abf7a..bff54263790 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3skip.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3skip.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3skip.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3sort.sty b/Master/texmf-dist/tex/latex/l3kernel/l3sort.sty index 618a56f4d66..9c562ad9755 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3sort.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3sort.sty @@ -41,6 +41,7 @@ \old@liii@module@name{This package is obsolete --- use 'expl3' instead} \RequirePackage{expl3} + %% %% %% End of file `l3sort.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3str.sty b/Master/texmf-dist/tex/latex/l3kernel/l3str.sty index d1e5a9b7512..1f7effda4f6 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3str.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3str.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3str.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3tl.sty b/Master/texmf-dist/tex/latex/l3kernel/l3tl.sty index f3e6f71ab09..4faa54e46e2 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3tl.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3tl.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3tl.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3token.sty b/Master/texmf-dist/tex/latex/l3kernel/l3token.sty index dfdf3bde38f..53f89cae6fc 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3token.sty +++ b/Master/texmf-dist/tex/latex/l3kernel/l3token.sty @@ -44,6 +44,7 @@ use 'expl3' instead} \@ehc \RequirePackage{expl3} + %% %% %% End of file `l3token.sty'. diff --git a/Master/texmf-dist/tex/latex/l3kernel/l3xdvipdfmx.def b/Master/texmf-dist/tex/latex/l3kernel/l3xdvipdfmx.def index 53f51576a3c..80de21c81dd 100644 --- a/Master/texmf-dist/tex/latex/l3kernel/l3xdvipdfmx.def +++ b/Master/texmf-dist/tex/latex/l3kernel/l3xdvipdfmx.def @@ -25,40 +25,9 @@ \cs_new_protected:Npn \__driver_literal:n #1 { \tex_special:D { pdf:literal~ #1 } } \cs_new_protected:Npn \__driver_scope_begin: - { \__driver_literal:n { q } } + { \tex_special:D { x:gsave } } \cs_new_protected:Npn \__driver_scope_end: - { \__driver_literal:n { Q } } -\cs_new_protected:Npn \__driver_matrix:n #1 - { \__driver_literal:n { #1 \c_space_tl 0~0~cm } } -\tl_new:N \l__driver_current_color_tl -\tl_set:Nn \l__driver_current_color_tl { [ 0 ] } -\AtBeginDocument - { - \@ifpackageloaded { color } - { \tl_set:Nn \l__driver_current_color_tl { \current@color } } - { } - } -\cs_new_protected:Npn \__driver_color_ensure_current: - { - \tex_special:D { pdf:bcolor~\l__driver_current_color_tl } - \group_insert_after:N \__driver_color_reset: - } -\cs_new_protected:Npn \__driver_color_reset: - { \tex_special:D { pdf:ecolor } } -\AtBeginDocument - { - \@ifpackageloaded { color } - { - \cs_set_protected:Npn \__driver_color_ensure_current: - { - \tex_special:D { color~push~\l__driver_current_color_tl } - \group_insert_after:N \__driver_color_reset: - } - \cs_set_protected:Npn \__driver_color_reset: - { \tex_special:D { color~pop } } - } - { } - } + { \tex_special:D { x:grestore } } \cs_new_protected:Npn \__driver_box_use_clip:N #1 { \__driver_scope_begin: @@ -77,41 +46,57 @@ \cs_new_protected:Npn \__driver_box_use_rotate:Nn #1#2 { \__driver_scope_begin: - \box_set_wd:Nn #1 \c_zero_dim - \fp_set:Nn \l__driver_cos_fp { round ( cosd ( #2 ) , 5 ) } - \fp_compare:nNnT \l__driver_cos_fp = \c_zero_fp - { \fp_zero:N \l__driver_cos_fp } - \fp_set:Nn \l__driver_sin_fp { round ( sind ( #2 ) , 5 ) } - \__driver_matrix:n + \tex_special:D { - \fp_use:N \l__driver_cos_fp \c_space_tl - \fp_compare:nNnTF \l__driver_sin_fp = \c_zero_fp - { 0~0 } - { - \fp_use:N \l__driver_sin_fp - \c_space_tl - \fp_eval:n { -\l__driver_sin_fp } - } - \c_space_tl - \fp_use:N \l__driver_cos_fp + x:rotate~ + \fp_compare:nNnTF {#2} = \c_zero_fp + { 0 } + { \fp_eval:n { round ( #2 , 5 ) } } } - \box_use:N #1 - \__driver_scope_end: + \box_use:N #1 + \__driver_scope_end: } -\fp_new:N \l__driver_cos_fp -\fp_new:N \l__driver_sin_fp \cs_new_protected:Npn \__driver_box_use_scale:Nnn #1#2#3 { \__driver_scope_begin: - \__driver_matrix:n + \tex_special:D { + x:scale~ \fp_eval:n { round ( #2 , 5 ) } ~ - 0~0~ \fp_eval:n { round ( #3 , 5 ) } } \hbox_overlap_right:n { \box_use:N #1 } \__driver_scope_end: } +\tl_new:N \l__driver_current_color_tl +\tl_set:Nn \l__driver_current_color_tl { [ 0 ] } +\AtBeginDocument + { + \@ifpackageloaded { color } + { \tl_set:Nn \l__driver_current_color_tl { \current@color } } + { } + } +\cs_new_protected:Npn \__driver_color_ensure_current: + { + \tex_special:D { pdf:bcolor~\l__driver_current_color_tl } + \group_insert_after:N \__driver_color_reset: + } +\cs_new_protected:Npn \__driver_color_reset: + { \tex_special:D { pdf:ecolor } } +\AtBeginDocument + { + \@ifpackageloaded { color } + { + \cs_set_protected:Npn \__driver_color_ensure_current: + { + \tex_special:D { color~push~\l__driver_current_color_tl } + \group_insert_after:N \__driver_color_reset: + } + \cs_set_protected:Npn \__driver_color_reset: + { \tex_special:D { color~pop } } + } + { } + } \cs_new_eq:NN \__driver_draw_literal:n \__driver_literal:n \cs_generate_variant:Nn \__driver_draw_literal:n { x } \cs_new_protected:Npn \__driver_draw_begin: diff --git a/Master/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty b/Master/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty index 05598c500d7..6b8976fe27d 100644 --- a/Master/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +++ b/Master/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty @@ -19,8 +19,8 @@ %% and all files in that bundle must be distributed together. %% %% File: l3keys2e.dtx (C) Copyright 2009,2011-2017 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{l3keys2e}{Support package l3kernel too old} @@ -32,7 +32,7 @@ }% \endinput } -\ProvidesExplPackage{l3keys2e}{2017/04/01}{} +\ProvidesExplPackage{l3keys2e}{2017/05/13}{} {LaTeX2e option processing using LaTeX3 keys} \cs_generate_variant:Nn \clist_put_right:Nn { Nv } \cs_generate_variant:Nn \keys_if_exist:nnT { nx } diff --git a/Master/texmf-dist/tex/latex/l3packages/xfp/xfp.sty b/Master/texmf-dist/tex/latex/l3packages/xfp/xfp.sty index 6d1e87919e3..306c0b6ed95 100644 --- a/Master/texmf-dist/tex/latex/l3packages/xfp/xfp.sty +++ b/Master/texmf-dist/tex/latex/l3packages/xfp/xfp.sty @@ -19,8 +19,8 @@ %% and all files in that bundle must be distributed together. %% %% File: xfp.dtx (C) Copyright 2017 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{xfpu}{Support package l3kernel too old} @@ -33,7 +33,7 @@ \endinput } \RequirePackage{xparse} -\ProvidesExplPackage{xfp}{2017/04/01}{} +\ProvidesExplPackage{xfp}{2017/05/13}{} {L3 Floating point unit} \NewExpandableDocumentCommand \fpeval { m } { \fp_eval:n {#1} } %% diff --git a/Master/texmf-dist/tex/latex/l3packages/xfrac/xfrac.sty b/Master/texmf-dist/tex/latex/l3packages/xfrac/xfrac.sty index 0321ddae4c5..db51d303b99 100644 --- a/Master/texmf-dist/tex/latex/l3packages/xfrac/xfrac.sty +++ b/Master/texmf-dist/tex/latex/l3packages/xfrac/xfrac.sty @@ -20,8 +20,8 @@ %% %% File: xfrac.dtx Copyright (C) 2004, 2008-2010 Morten Hoegholm %% (C) 2011,2012,2014-2017 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{xfrac}{Support package l3kernel too old} @@ -34,7 +34,7 @@ \endinput } \RequirePackage{amstext,graphicx,l3keys2e,textcomp,xparse,xtemplate} -\ProvidesExplPackage{xfrac}{2017/04/01}{} +\ProvidesExplPackage{xfrac}{2017/05/13}{} {L3 Experimental split-level fractions} \keys_define:nn { xfrac } { diff --git a/Master/texmf-dist/tex/latex/l3packages/xparse/xparse.sty b/Master/texmf-dist/tex/latex/l3packages/xparse/xparse.sty index d266150d793..14e8e59eec0 100644 --- a/Master/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +++ b/Master/texmf-dist/tex/latex/l3packages/xparse/xparse.sty @@ -23,8 +23,8 @@ %% (C) Copyright 2004-2008 Frank Mittelbach, %% The LaTeX3 Project %% (C) Copyright 2009-2017 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{xparse}{Support package l3kernel too old} @@ -36,7 +36,7 @@ }% \endinput } -\ProvidesExplPackage{xparse}{2017/04/01}{} +\ProvidesExplPackage{xparse}{2017/05/13}{} {L3 Experimental document command parser} \tl_const:Nx \c__xparse_no_value_tl { \char_generate:nn { `\- } { 11 } NoValue- } @@ -285,36 +285,18 @@ } \cs_new_protected:Npn \__xparse_defaults_def:nnn #1#2#3 { - \tl_if_head_is_group:nTF {#3} + \tl_put_right:Nx \l__xparse_tmpa_tl { - \tl_put_right:Nn \l__xparse_tmpa_tl - { + { + \exp_not:N \exp_not:n { - \exp_args:Nf \__xparse_tl_mapthread_function:nnN - { \tl_item:Nn \l__xparse_args_tl {#1} } - {#3} - \__xparse_defaults_def_aux:nn + \__xparse_if_no_value:nTF {#2} + { \exp_not:o {#3} } + { \exp_not:n { ## #1 } } } - } - } - { - \__xparse_if_no_value:nTF {#2} - { - \tl_put_right:Nx \l__xparse_tmpa_tl - { { \exp_not:N \exp_not:n { \exp_not:o {#3} } } } - } - { - \tl_put_right:Nn \l__xparse_tmpa_tl - { { \exp_not:n { ## #1 } } } - } + } } } -\cs_new:Npn \__xparse_defaults_def_aux:nn #1#2 - { - \__xparse_if_no_value:nTF {#1} - { { \exp_not:n {#2} } } - { { \exp_not:n {#1} } } - } \cs_new_protected:Npn \__xparse_args_process: { \tl_clear:N \l__xparse_args_ii_tl @@ -367,28 +349,9 @@ } \cs_new:Npn \__xparse_end_expandable_defaults:nnw #1#2 { - \tl_if_head_is_group:nTF {#1} - { - \__xparse_end_expandable_defaults_E:nnw { } - #1 \q_nil \q_mark - #2 \q_nil - } - { - \__xparse_if_no_value:nTF {#2} - { \exp_args:No \__xparse_end_expandable_defaults:nw {#1} } - { \__xparse_end_expandable_defaults:nw {#2} } - } - } -\cs_new:Npn \__xparse_end_expandable_defaults_E:nnw #1#2#3 \q_mark #4 - { - \quark_if_nil:nTF {#2} - { \__xparse_end_expandable_defaults:nw {#1} } - { - \__xparse_if_no_value:nTF {#4} - { \__xparse_end_expandable_defaults_E:nnw { #1 {#2} } } - { \__xparse_end_expandable_defaults_E:nnw { #1 {#4} } } - #3 \q_mark - } + \__xparse_if_no_value:nTF {#2} + { \exp_args:No \__xparse_end_expandable_defaults:nw {#1} } + { \__xparse_end_expandable_defaults:nw {#2} } } \cs_new:Npn \__xparse_end_expandable_defaults:nw #1#2 \__xparse_end_expandable_defaults:nnnNNn #3 @@ -506,6 +469,7 @@ \__xparse_add_arg_spec:n { E {#1} {#2} } \tl_put_right:Nn \l__xparse_last_delimiters_tl {#1} \bool_set_false:N \l__xparse_grab_expandably_bool + \int_add:Nn \l__xparse_current_arg_int { \tl_count:n {#1} - 1 } \__xparse_normalize_arg_spec_loop:n } \cs_new_protected:Npn \__xparse_normalize_E_unique_check:w #1#2 \q_stop @@ -672,7 +636,6 @@ \cs_new_protected:Npn \__xparse_prepare_signature_bypass:N #1 { \quark_if_recursion_tail_stop:N #1 - \int_incr:N \l__xparse_current_arg_int \use:c { __xparse_add @@ -685,7 +648,6 @@ \__xparse_flush_m_args: \bool_set_true:N \l__xparse_long_bool \bool_set_true:N \l__xparse_prefixed_bool - \int_decr:N \l__xparse_current_arg_int \__xparse_prepare_signature_bypass:N } \cs_new_protected:cpn { __xparse_add_type_>:w } #1 @@ -693,7 +655,6 @@ \__xparse_flush_m_args: \bool_set_true:N \l__xparse_prefixed_bool \bool_set_true:N \l__xparse_process_some_bool - \int_decr:N \l__xparse_current_arg_int \tl_put_left:Nn \l__xparse_process_one_tl { {#1} } \__xparse_prepare_signature_bypass:N } @@ -814,30 +775,26 @@ \__xparse_if_no_value:nTF {#1} { \__xparse_add_default: } { + \int_incr:N \l__xparse_current_arg_int \bool_set_true:N \l__xparse_defaults_bool \tl_put_right:Nn \l__xparse_defaults_tl { { \prg_do_nothing: #1 } } } } \cs_new_protected:Npn \__xparse_add_default: - { \tl_put_right:Nn \l__xparse_defaults_tl { \c__xparse_no_value_tl } } + { + \int_incr:N \l__xparse_current_arg_int + \tl_put_right:Nn \l__xparse_defaults_tl { \c__xparse_no_value_tl } + } \cs_new_protected:Npn \__xparse_add_default_E:nn #1#2 { - \bool_set_true:N \l__xparse_defaults_bool - \tl_put_right:Nx \l__xparse_defaults_tl - { - { - \tl_map_function:nN {#2} \__xparse_add_default_E_aux:n - \prg_replicate:nn - { \tl_count:n {#1} - \tl_count:n {#2} } - { { \c__xparse_no_value_tl } } - } - } + \tl_map_function:nN {#2} \__xparse_add_default:n + \prg_replicate:nn + { \tl_count:n {#1} - \tl_count:n {#2} } + { \__xparse_add_default: } } -\cs_new:Npn \__xparse_add_default_E_aux:n #1 { \exp_not:n { {#1} } } \cs_new_protected:cpn { __xparse_add_expandable_type_+:w } { \bool_set_true:N \l__xparse_long_bool - \int_decr:N \l__xparse_current_arg_int \__xparse_prepare_signature:N } \cs_new_protected:Npn \__xparse_add_expandable_type_D:w @@ -1091,18 +1048,14 @@ \tl_set:Nn \l__xparse_signature_tl {#2} \cs_set_protected:Npn \__xparse_grab_E_finalise: { - \tl_clear:N \l__xparse_tmpa_tl \tl_map_inline:nn {#1} { \prop_get:NnNF \l__xparse_tmp_prop {####1} \l__xparse_tmpb_tl { \tl_set_eq:NN \l__xparse_tmpb_tl \c__xparse_no_value_tl } - \tl_set:Nx \l__xparse_tmpa_tl - { - \exp_not:V \l__xparse_tmpa_tl - { \exp_not:V \l__xparse_tmpb_tl } - } + \tl_put_right:Nx \l__xparse_args_tl + { { \exp_not:V \l__xparse_tmpb_tl } } } - \__xparse_add_arg:V \l__xparse_tmpa_tl + \l__xparse_signature_tl \__xparse_run_code: } \__xparse_grab_E_loop:nnN {#4} { } #1 \q_recursion_tail \q_recursion_stop } @@ -1540,7 +1493,7 @@ \cs_new:Npn \__xparse_expandable_grab_E_find:nnw #1#2#3 \q_nil #4 \q__xparse #5#6#7#8 { \__xparse_expandable_grab_E_aux:w {#1} { #2 {#8} #3 } #4 \q__xparse #5 #6 #7 } \cs_new:Npn \__xparse_expandable_grab_E_end:nnw #1#2#3 \q__xparse #4#5#6 - { #3 {#2} \q__xparse #4 #5 {#1} } + { #3 #2 \q__xparse #4 #5 {#1} } \cs_new:Npn \__xparse_expandable_grab_m:w #1 \q__xparse #2#3 { #3 { \__xparse_expandable_grab_m_aux:wNn #1 \q__xparse #2 #3 } } \cs_new:Npn \__xparse_expandable_grab_m_long:w #1 \q__xparse #2#3 diff --git a/Master/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.sty b/Master/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.sty index d3a040d8b8d..91b6e775335 100644 --- a/Master/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.sty +++ b/Master/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.sty @@ -23,8 +23,8 @@ %% (C) Copyright 2004-2010 Frank Mittelbach, %% The LaTeX3 Project %% (C) Copyright 2011-2016 The LaTeX3 Project -\RequirePackage{expl3}[2017/04/01] -\@ifpackagelater{expl3}{2017/04/01} +\RequirePackage{expl3}[2017/05/13] +\@ifpackagelater{expl3}{2017/05/13} {} {% \PackageError{xtemplate}{Support package l3kernel too old} @@ -36,7 +36,7 @@ }% \endinput } -\ProvidesExplPackage{xtemplate}{2017/04/01}{} +\ProvidesExplPackage{xtemplate}{2017/05/13}{} {L3 Experimental prototype document functions} \tl_const:Nn \c__xtemplate_code_root_tl { template~code~>~ } \tl_const:Nn \c__xtemplate_defaults_root_tl { template~defaults~>~ } |