summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/unravel
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-09-30 21:17:21 +0000
committerKarl Berry <karl@freefriends.org>2015-09-30 21:17:21 +0000
commitb9f09946a8fe2f81468fb7bf624e3f8ce2d26888 (patch)
tree0c5e5d740d31c1239d420feb4b7b64f3e707e85f /Master/texmf-dist/source/latex/unravel
parent2f667f4d777c2ce38eb648f49ae5fde2c644dcfc (diff)
unravel (30sep15)
git-svn-id: svn://tug.org/texlive/trunk@38506 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/unravel')
-rw-r--r--Master/texmf-dist/source/latex/unravel/unravel.dtx893
1 files changed, 712 insertions, 181 deletions
diff --git a/Master/texmf-dist/source/latex/unravel/unravel.dtx b/Master/texmf-dist/source/latex/unravel/unravel.dtx
index 87170f4286c..328b20512ed 100644
--- a/Master/texmf-dist/source/latex/unravel/unravel.dtx
+++ b/Master/texmf-dist/source/latex/unravel/unravel.dtx
@@ -23,9 +23,9 @@
%
% \title{The \textsf{unravel} package: \\
% watching TeX digest tokens\thanks{This
-% file has version number 0.1, last revised 2015/09/22.}}
+% file has version number 0.2, last revised 2015/09/30.}}
% \author{Bruno Le Floch}
-% \date{2015/09/22}
+% \date{2015/09/30}
%
% \maketitle
% \tableofcontents
@@ -202,9 +202,21 @@
% \item Some primitives are not implemented yet: alignments
% (\tn{halign}, \tn{valign}, \tn{noalign}, \tn{omit}, \tn{span},
% \tn{cr}, \tn{crcr},~|&|), many math mode primitives, and
-% \cs{pdfprimitive}, \cs{aftergroup}, \cs{discretionary}, as well as
+% \tn{pdfprimitive}, \tn{discretionary}, as well as
% all primitives specific to engines other than \pdfTeX{}.
-% This list is sadly incomplete!
+% This list may sadly be incomplete!
+% \item \tn{aftergroup} is only partially implemented.
+% \item \tn{everyhbox}, \tn{everyvbox}, \tn{everymath},
+% \tn{everydisplay}, \tn{lastkern}, \tn{lastnodetype},
+% \tn{lastpenalty}, \tn{lastskip}, \tn{currentiflevel} and
+% \tn{currentiftype} may have wrong values. Perhaps
+% \tn{currentgrouplevel} and \tn{currentgrouptype} too.
+% \item Tokens passed to \tn{afterassignment} are not yet kept after
+% \pkg{unravel} is done even if there has been no assignment.
+% \item Tokens passed to \tn{aftergroup} are lost when \pkg{unravel} is
+% done.
+% \item In \XeTeX{}, characters beyond the basic multilingual plane may
+% break \pkg{unravel} (not tested).
% \item For \pkg{unravel}, category codes are fixed when a file is read
% using \tn{input},
% while \TeX{} only fixes category codes when the corresponding
@@ -227,6 +239,16 @@
% \item Allow to replay steps that have already been run.
% \item Fix the display for \tn{if} and \tn{ifcat} (remove extraneous
% \cs{exp_not:N}).
+% \item Use the |file-error| fatal error message: first implement
+% \cs{@@_file_if_exist:nTF} and use it to determine whether
+% \tn{input} will throw a fatal error in \tn{batchmode} and
+% \tn{nonstopmode}.
+% \item Use the |interwoven-preambles| fatal error message once
+% alignments are implemented.
+% \item Look at all places where \TeX{}'s procedure |prepare_mag| is
+% called.
+% \item Find out why so many input levels are used (see the log of the
+% |unravel003| testfile for instance)
% \end{itemize}
%
% \end{documentation}
@@ -243,21 +265,251 @@
% \end{macrocode}
%
% \begin{macrocode}
-\RequirePackage{expl3,xparse}[2015/09/11]
-\RequirePackage{gtl}[2015/09/21]
-\ProvidesExplPackage
- {unravel} {2015/09/22} {0.1} {Watching TeX digest tokens}
+%<@@=unravel>
+% \end{macrocode}
+%
+% Catcode settings. In a group, set |\c| to be a synonym of |\catcode|
+% for short, set the catcode of space to be 10 (using |\fam| to avoid
+% needing a space or an equal sign to separate the two integer
+% arguments of |\catcode|) and that of |%| to be 14 (using |\fam| again
+% to avoid needing the digit 7 to have catcode other: we need the digit
+% 5 anyway in two steps). Then make |-|, |6|, |7|, |8|, |9| other (we
+% must assume that |0| through |5| are already other), and make |:|,
+% |_|, |h|, |j|, |k|, |q|, |s|, |w|, |x|, |y|, |z| letters (other
+% lowercase letters already need to be letters in the rest of the
+% code). Make sure there is no |\endlinechar|. We are finally ready
+% to safely test whether the package has already been loaded and bail
+% out in case it has. Expanding |\fi| before ending the group ensures
+% that the whole line has been read by \TeX{} before restoring earlier
+% catcodes.
+% \begin{macrocode}
+\begingroup\let\c\catcode\fam32\c\fam10\advance\fam5\c\fam14\c45 12 %
+\c54 12\c55 12\c56 12\c57 12\c58 11\c95 11\c104 11\c106 11\c107 11 %
+\c113 11\c115 11\c119 11\c120 11\c121 11\c122 11\endlinechar-1 %
+\expandafter\ifx\csname unravel\endcsname\relax
+\else\endinput\expandafter\endgroup\fi
+% \end{macrocode}
+%
+% Set |T| and |X| to be letters for an error message. Set up braces
+% and |#| for definitions, |=| for nicer character code assignments,
+% |>| for integer comparison, |+| for integer expressions.
+% \begin{macrocode}
+\c84 11\c88 11\c35 6\c123 1\c125 2\c62 12\c61 12\c43 12 %
+% \end{macrocode}
+%
+% If \eTeX{}'s \tn{numexpr} or \tn{protected} are not available, bail
+% out with an error.
+% \begin{macrocode}
+\expandafter\ifx\csname numexpr\endcsname\relax
+\errmessage{unravel requires \numexpr from eTeX}
+\endinput\expandafter\endgroup\fi
+\expandafter\ifx\csname protected\endcsname\relax
+\errmessage{unravel requires \protected from eTeX}
+\endinput\expandafter\endgroup\fi
+% \end{macrocode}
+%
+% If \pkg{unravel} is loaded within a group, bail out because
+% \pkg{expl3} would not be loaded properly.
+% \begin{macrocode}
+\expandafter\ifx\csname currentgrouplevel\endcsname\relax\else
+\ifnum\currentgrouplevel>1 \errmessage{unravel loaded in a group}
+\endinput\expandafter\expandafter\expandafter\endgroup\fi\fi
+% \end{macrocode}
+%
+% Make spaces ignored and make |~| a space, to prettify code.
+% \begin{macrocode}
+\catcode 32 = 9 \relax
+\catcode 126 = 10 \relax
+% \end{macrocode}
+%
+% \begin{variable}{\l_@@_setup_restore_tl}
+% This token list variable will contain code to restore category
+% codes to their value when the package was loaded.
+% \begin{macrocode}
+\gdef \l_@@_setup_restore_tl { }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[int]{\@@_setup_restore:}
+% Use the token list to restore catcodes to their former values, then
+% empty the list since there is no catcode to restore anymore. This
+% mechanism cannot be nested.
+% \begin{macrocode}
+\protected \gdef \@@_setup_restore:
+ {
+ \l_@@_setup_restore_tl
+ \def \l_@@_setup_restore_tl { }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_setup_save:}
+% \begin{macro}[aux, EXP]{\@@_setup_save_aux:n}
+% This saves into \cs{l_@@_setup_restore_tl} the current catcodes
+% (from $0$ to $255$ only), \tn{endlinechar}, \tn{escapechar},
+% \tn{newlinechar}.
+% \begin{macrocode}
+\protected \gdef \@@_setup_save:
+ {
+ \edef \l_@@_setup_restore_tl
+ {
+ \@@_setup_save_aux:w 0 =
+ \endlinechar = \the \endlinechar
+ \escapechar = \the \escapechar
+ \newlinechar = \the \newlinechar
+ \relax
+ }
+ }
+\long \gdef \@@_setup_save_aux:w #1 =
+ {
+ \catcode #1 = \the \catcode #1 ~
+ \ifnum 255 > #1 ~
+ \expandafter \@@_setup_save_aux:w
+ \the \numexpr #1 + 1 \expandafter =
+ \fi
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_setup_catcodes:nnn}
+% This sets all characters from |#1| to |#2| (inclusive) to have
+% catcode |#3|.
+% \begin{macrocode}
+\protected \long \gdef \@@_setup_catcodes:nnn #1 #2 #3
+ {
+ \ifnum #1 > #2 ~ \else
+ \catcode #1 = #3 ~
+ \expandafter \@@_setup_catcodes:nnn \expandafter
+ { \the \numexpr #1 + 1 } {#2} {#3}
+ \fi
+ }
% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_setup_latexe:}
+% This saves the catcodes and related parameters, then sets them to
+% the value they normally have in a \LaTeXe{} package (in particular,
+% |@| is a letter).
+% \begin{macrocode}
+\protected \gdef \@@_setup_latexe:
+ {
+ \@@_setup_save:
+ \@@_setup_catcodes:nnn {0} {8} {15}
+ \catcode 9 = 10 ~
+ \catcode 10 = 12 ~
+ \catcode 11 = 15 ~
+ \catcode 12 = 13 ~
+ \catcode 13 = 5 ~
+ \@@_setup_catcodes:nnn {14} {31} {15}
+ \catcode 32 = 10 ~
+ \catcode 33 = 12 ~
+ \catcode 34 = 12 ~
+ \catcode 35 = 6 ~
+ \catcode 36 = 3 ~
+ \catcode 37 = 14 ~
+ \catcode 38 = 4 ~
+ \@@_setup_catcodes:nnn {39} {63} {12}
+ \@@_setup_catcodes:nnn {64} {90} {11}
+ \catcode 91 = 12 ~
+ \catcode 92 = 0 ~
+ \catcode 93 = 12 ~
+ \catcode 94 = 7 ~
+ \catcode 95 = 8 ~
+ \catcode 96 = 12 ~
+ \@@_setup_catcodes:nnn {97} {122} {11}
+ \catcode 123 = 1 ~
+ \catcode 124 = 12 ~
+ \catcode 125 = 2 ~
+ \catcode 126 = 13 ~
+ \catcode 127 = 15 ~
+ \@@_setup_catcodes:nnn {128} {255} {12}
+ \endlinechar = 13 ~
+ \escapechar = 92 ~
+ \newlinechar = 10 ~
+ }
+% \end{macrocode}
+% \end{macro}
%
+% \begin{macro}[int]{\@@_setup_unravel:}
+% Catcodes for \pkg{unravel} (in particular, |@| is other, |:| and
+% |_| are letters, spaces are ignored, |~| is a space).
+% \begin{macrocode}
+\protected \gdef \@@_setup_unravel:
+ {
+ \@@_setup_save:
+ \@@_setup_catcodes:nnn {0} {8} {15}
+ \catcode 9 = 9 ~
+ \catcode 10 = 12 ~
+ \catcode 11 = 15 ~
+ \catcode 12 = 13 ~
+ \catcode 13 = 5 ~
+ \@@_setup_catcodes:nnn {14} {31} {15}
+ \catcode 32 = 9 ~
+ \catcode 33 = 12 ~
+ \catcode 34 = 12 ~
+ \catcode 35 = 6 ~
+ \catcode 36 = 3 ~
+ \catcode 37 = 14 ~
+ \catcode 38 = 4 ~
+ \@@_setup_catcodes:nnn {39} {57} {12}
+ \catcode 58 = 11 ~
+ \@@_setup_catcodes:nnn {59} {64} {12}
+ \@@_setup_catcodes:nnn {65} {90} {11}
+ \catcode 91 = 12 ~
+ \catcode 92 = 0 ~
+ \catcode 93 = 12 ~
+ \catcode 94 = 7 ~
+ \catcode 95 = 11 ~
+ \catcode 96 = 12 ~
+ \@@_setup_catcodes:nnn {97} {122} {11}
+ \catcode 123 = 1 ~
+ \catcode 124 = 12 ~
+ \catcode 125 = 2 ~
+ \catcode 126 = 10 ~
+ \catcode 127 = 15 ~
+ \@@_setup_catcodes:nnn {128} {255} {12}
+ \escapechar = 92 ~
+ \endlinechar = 32 ~
+ \newlinechar = 10 ~
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% End the group where all catcodes where changed, but expand
+% \cs{@@_setup_latexe:} to sanitize catcodes again outside the
+% group. The catcodes are saved.
+% \begin{macrocode}
+\expandafter \endgroup \@@_setup_latexe:
+% \end{macrocode}
+%
+% Load a few dependencies: \pkg{expl3}, \pkg{xparse}, \pkg{gtl}.
% Load \pkg{l3str} if \pkg{expl3} is too old and does not define
% \cs{str_range:nnn}. Otherwise loading \pkg{l3str} would give
% an error.
% \begin{macrocode}
-\cs_if_exist:NF \str_range:nnn { \RequirePackage{l3str} }
+\RequirePackage{expl3,xparse}[2015/09/11]
+\RequirePackage{gtl}[2015/09/21]
+\csname cs_if_exist:cF\endcsname{str_range:nnn}{\RequirePackage{l3str}}
% \end{macrocode}
%
+% Before loading \pkg{unravel}, restore catcodes, so that the implicit
+% \cs{ExplSyntaxOn} in \cs{ProvidesExplPackage} picks up the correct
+% catcodes to restore when \cs{ExplSyntaxOff} is run at the end of the
+% package. The place where catcodes are restored are beyond
+% \pkg{unravel}'s reach, which is why we cannot bypass \pkg{expl3} and
+% simply restore the catcodes once everything is done. To avoid issues
+% with crazy catcodes, make \TeX{} read the arguments of
+% \cs{ProvidesExplPackage} before restoring catcodes. Then immediately
+% go to the catcodes we want.
% \begin{macrocode}
-%<@@=unravel>
+\csname use:n\endcsname
+ {%
+ \csname @@_setup_restore:\endcsname
+ \ProvidesExplPackage
+ {unravel} {2015/09/30} {0.2} {Watching TeX digest tokens}%
+ \csname @@_setup_unravel:\endcsname
+ }%
% \end{macrocode}
%
% \subsection{Primitives, variants, and helpers}
@@ -281,6 +533,7 @@
\cs_new_eq:NN \@@_everyeof:w \etex_everyeof:D
\cs_new_eq:NN \@@_everypar:w \tex_everypar:D
\cs_new_eq:NN \@@_hbox:w \tex_hbox:D
+\cs_new_eq:NN \@@_mag: \tex_mag:D
\cs_new_eq:NN \@@_nullfont: \tex_nullfont:D
\cs_new_eq:NN \@@_the:w \tex_the:D
% \end{macrocode}
@@ -299,24 +552,15 @@
%
% Variants that we need.
% \begin{macrocode}
-\cs_if_exist:NF \exp_last_unbraced:NNn
- { \cs_new_eq:NN \exp_last_unbraced:NNn \use:nnn }
-\cs_generate_variant:Nn \exp_last_unbraced:NNn { NNv }
\cs_generate_variant:Nn \str_head:n { f }
\cs_generate_variant:Nn \tl_to_str:n { o }
\cs_generate_variant:Nn \tl_if_head_eq_meaning:nNT { V }
-\cs_generate_variant:Nn \tl_if_head_is_space:nTF { o }
-\cs_generate_variant:Nn \tl_if_head_is_space:nT { V }
-\cs_generate_variant:Nn \tl_if_head_is_N_type:nTF { o }
\cs_generate_variant:Nn \tl_if_in:nnF { nV }
\cs_generate_variant:Nn \tl_if_in:nnTF { nV }
-\cs_generate_variant:Nn \tl_if_eq:nnT { V }
\cs_generate_variant:Nn \tl_if_in:NnTF { No , NV }
\cs_generate_variant:Nn \tl_if_single_token:nT { V }
\cs_generate_variant:Nn \tl_gset_rescan:Nnn { Nnx }
-\cs_generate_variant:Nn \gtl_gput_left:Nn { Nx , NV , No }
-\cs_generate_variant:Nn \gtl_gput_right:Nn { Nx , NV }
-\cs_generate_variant:Nn \gtl_put_right:Nn { NV }
+\cs_generate_variant:Nn \gtl_gput_right:Nn { NV }
\cs_generate_variant:Nn \ior_get_str:NN { Nc }
\cs_generate_variant:Nn \gtl_if_empty:NTF { c }
\cs_generate_variant:Nn \gtl_to_str:N { c }
@@ -337,31 +581,97 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\@@_tl_gset_input:Nnn, \@@_tl_gset_input:Nno}
-% \begin{macro}[aux]{\@@_tl_gset_input_aux:wN}
+% \begin{macro}[aux]{\@@_file_get:nN}
+% \begin{macro}[aux]{\@@_file_get_aux:wN}
% \begin{macrocode}
-\cs_new_protected:Npn \@@_tl_gset_input:Nnn #1#2#3
+\cs_set_protected:Npn \@@_tmp:w #1
{
- \group_begin:
- \@@_everyeof:w \exp_after:wN { \token_to_str:N @ @ #1 }
- #2
- \tl_gclear:N #1
- \exp_after:wN \@@_tl_gset_input_aux:wN
- \exp_after:wN \prg_do_nothing:
- \tex_input:D \tl_to_str:n {#3} \scan_stop:
- \group_end:
- \tl_gput_right:NV #1 \@@_everyeof:w
+ \cs_new_protected:Npn \@@_file_get:nN ##1##2
+ {
+ \group_begin:
+ \@@_everyeof:w { #1 ##2 }
+ \exp_after:wN \@@_file_get_aux:wN
+ \exp_after:wN \prg_do_nothing:
+ \tex_input:D ##1 \scan_stop:
+ }
+ \cs_new_protected:Npn \@@_file_get_aux:wN ##1 #1 ##2
+ {
+ \group_end:
+ \tl_set:Nx ##2
+ { \exp_not:o {##1} \exp_not:V \@@_everyeof:w }
+ }
}
-\cs_generate_variant:Nn \@@_tl_gset_input:Nnn { Nno }
-\use:x
+\exp_args:No \@@_tmp:w { \token_to_str:N : : }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_tl_first_int:N}
+% \begin{macro}[aux, EXP]{\@@_tl_first_int_aux:Nn}
+% Function that finds an explicit number in a token list. This is
+% used for instance when implementing \tn{read}, to find the stream
+% \meta{number} within the whole \tn{read} \meta{number} |to|
+% \meta{cs} construction. The auxiliary initially has itself as a
+% first argument, and once a first digit is found it has
+% \cs{use_none_delimit_by_q_stop:w}. That first argument is used
+% whenever what follows is not a digit, hence initially we loop,
+% while after the first digit is found any non-digit stops the
+% recursion. If no integer is found, $0$ is left in the token list.
+% The surrounding \cs{int_eval:n} lets us dump digits in the input
+% stream while keeping the function fully expandable.
+% \begin{macrocode}
+\cs_new:Npn \@@_tl_first_int:N #1
{
- \cs_new_protected:Npn \exp_not:N \@@_tl_gset_input_aux:wN
- ##1 \token_to_str:N @ @ ##2
- } { \tl_gset:No #2 {#1} }
+ \int_eval:n
+ {
+ \exp_after:wN \@@_tl_first_int_aux:Nn
+ \exp_after:wN \@@_tl_first_int_aux:Nn
+ #1 ? 0 ? \q_stop
+ }
+ }
+\cs_new:Npn \@@_tl_first_int_aux:Nn #1#2
+ {
+ \tl_if_single:nT {#2}
+ {
+ \token_if_eq_catcode:NNT + #2
+ {
+ \if_int_compare:w 1 < 1 #2 \exp_stop_f:
+ #2
+ \exp_after:wN \use_i_ii:nnn
+ \exp_after:wN \@@_tl_first_int_aux:Nn
+ \exp_after:wN \use_none_delimit_by_q_stop:w
+ \fi:
+ }
+ }
+ #1
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
+% \begin{macro}[int]{\@@_prepare_mag:}
+% Used whenever \TeX{} needs the value of \tn{mag}. ^^A todo: move
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_prepare_mag:
+ {
+ \int_compare:nNnT { \g_@@_mag_set_int } > { 0 }
+ {
+ \int_compare:nNnF { \@@_mag: } = { \g_@@_mag_set_int }
+ {
+ \@@_tex_error:nn { incompatible-mag } { }
+ \int_gset_eq:NN \@@_mag: \g_@@_mag_set_int
+ }
+ }
+ \int_compare:nF { 1 <= \@@_mag: <= 32768 }
+ {
+ \@@_tex_error:nV { illegal-mag } \l_@@_head_tl
+ \int_gset:Nn \@@_mag: { 1000 }
+ }
+ \int_gset_eq:NN \g_@@_mag_set_int \@@_mag:
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \subsubsection{String helpers}
%
% \begin{macro}[int]{\@@_strip_escape:w}
@@ -951,6 +1261,14 @@
% \end{macrocode}
% \end{variable}
%
+% \begin{variable}{\l_@@_after_group_gtl}
+% Tokens to insert after the current group ends. This variable must
+% be emptied at the beginning of every group.
+% \begin{macrocode}
+\gtl_new:N \l_@@_after_group_gtl
+% \end{macrocode}
+% \end{variable}
+%
% \begin{variable}{\c_@@_parameters_tl}
% Used to determine if a macro has simple parameters or not.
% \begin{macrocode}
@@ -1052,6 +1370,19 @@
% \end{macrocode}
% \end{variable}
%
+% \subsubsection{\TeX{} parameters}
+%
+% \begin{variable}{\g_@@_mag_set_int}
+% The first time \TeX{} uses the value of \tn{mag}, it stores it in a
+% global parameter |mag_set| (initially $0$ to denote not being set).
+% Any time \TeX{} needs the value of \tn{mag}, it checks that the
+% value matches |mag_set|. This is done in \pkg{unravel} by
+% \cs{@@_prepare_mag:}, storing |mag_set| in \cs{g_@@_mag_set_int}.
+% \begin{macrocode}
+\int_new:N \g_@@_mag_set_int
+% \end{macrocode}
+% \end{variable}
+%
% \subsection{Numeric codes}
% \label{sec:numeric-codes}
%
@@ -2516,7 +2847,7 @@
\bool_if:NT \g_@@_internal_debug_bool
{
\@@_set_cmd:
- \iow_term:x { Exp:~\int_use:N \l_@@_head_cmd_int }
+ \iow_term:x { Exp:~\int_to_arabic:n { \l_@@_head_cmd_int } }
}
\token_if_macro:NTF \l_@@_head_token
{ \@@_macro_call: }
@@ -2769,6 +3100,21 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}[aux]{\@@_scan_to:}
+% Used when |to| is mandatory: after \tn{read} or \tn{readline} and
+% after \tn{vsplit}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_scan_to:
+ {
+ \@@_scan_keyword:nF { tToO }
+ {
+ \msg_error:nn { unravel } { missing-to }
+ \@@_prev_input:n { to }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[aux]{\@@_scan_font_ident:}
% Find a font identifier.
% \begin{macrocode}
@@ -2794,8 +3140,8 @@
}
{
\msg_error:nn { unravel } { missing-font-id }
+ \@@_back_input:
\@@_prev_input:n { \@@_nullfont: }
- \@@_back_error:
}
}
% \end{macrocode}
@@ -2859,7 +3205,7 @@
% performed after placing the current token in a new level of
% |prev_input| and telling the user about it. Once done with this
% step, \cs{l_@@_head_tl} contains the tokens found. Convert them to
-% the wanted level with \cs{@@_thing_use:nN} (at this stage, \TeX{}
+% the wanted level with \cs{@@_thing_use_get:nnNN} (at this stage, \TeX{}
% may complain about a missing number or incompatible glue units), and
% place the result in |prev_input|. Finally, tell the user the tokens
% that have been found and their value (and, if there was a single
@@ -2880,7 +3226,11 @@
{
\int_compare:nNnTF
{ ( #1 + \c_two ) / \c_four } > { ( #3 + \c_two ) / \c_four }
- { \@@_back_input: }
+ {
+ \@@_back_input:
+ \msg_error:nn { unravel } { missing-something }
+ \tl_clear:N \l_@@_tmpa_tl
+ }
{
\tl_if_empty:nF {#2}
{
@@ -2889,9 +3239,8 @@
#2
\seq_gpop_right:NN \g_@@_prev_input_seq \l_@@_head_tl
}
+ \@@_thing_use_get:nnNN {#1} {#3} \l_@@_head_tl \l_@@_tmpa_tl
}
- \tl_set:Nx \l_@@_tmpa_tl
- { \@@_thing_use:nnN {#1} {#3} \l_@@_head_tl }
\@@_prev_input_silent:V \l_@@_tmpa_tl
\@@_set_action_text:
\@@_set_action_text:x
@@ -2937,9 +3286,9 @@
{ 83 } { 1 \@@_scan_int: } % set_box_dimen
{ 84 } { 0 \@@_scan_int: } % set_shape
{ 85 } { 0 \@@_scan_int: } % def_code
- { 86 } { 4 \@@_scan_font_ident: } % def_family
- { 87 } { 4 \@@_scan_font_ident: } % set_font
- { 88 } { 4 \@@_scan_font_ident: } % def_font
+ { 86 } { 4 \@@_scan_int: } % def_family
+ { 87 } { 4 } % set_font
+ { 88 } { 4 } % def_font
{ 89 } { \@@_thing_register: } % register
}
{ 8 }
@@ -3009,21 +3358,45 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux,EXP]{\@@_thing_use:nnN}
-% Given a level~|#1|, call a function to convert the token list~|#2|
-% to the correct level. This step may trigger \TeX{} errors, which
-% should precisely match the expected ones.
+% \begin{macro}[aux]{\@@_thing_use_get:nnNN}
+% Given a level found~|#1| and a target level~|#2| (with |#1| in
+% $[0,3]$ or |#1| and |#2| in $[4,5]$), turn the token list |#3| into
+% the desired level, and store the result in |#4|. This step may
+% trigger \TeX{} errors, which should precisely match the expected
+% ones.
% \begin{macrocode}
-\cs_new:Npn \@@_thing_use:nnN #1#2
+\cs_new_protected:Npn \@@_thing_use_get:nnNN #1#2#3#4
{
- \int_case:nnF { \int_min:nn {#1} {#2} }
+ \int_compare:nNnTF {#2} < { 3 }
+ {
+ \int_compare:nNnT {#1} = { 3 }
+ { \@@_tex_error:nV { incompatible-units } #3 }
+ \tl_set:Nx #4
+ {
+ \int_case:nn { \int_min:nn {#1} {#2} }
+ {
+ { 0 } \int_eval:n
+ { 1 } \dim_eval:n
+ { 2 } \skip_eval:n
+ }
+ { \int_compare:nNnT {#1} = { 3 } \etex_mutoglue:D #3 }
+ }
+ }
{
- { 0 } \int_eval:n
- { 1 } \dim_eval:n
- { 2 } \skip_eval:n
- { 3 } \muskip_eval:n
+ \int_compare:nNnTF {#2} = { 3 }
+ {
+ \int_case:nnF {#1}
+ {
+ { 0 } { \tl_set:Nx #4 { \int_eval:n {#3} } }
+ { 3 } { \tl_set:Nx #4 { \muskip_eval:n {#3} } }
+ }
+ {
+ \@@_tex_error:nV { incompatible-units } #3
+ \tl_set:Nx #4 { \muskip_eval:n { \etex_gluetomu:D #3 } }
+ }
+ }
+ { \tl_set:Nx #4 { \@@_the:w #3 } }
}
- { \@@_the:w }
}
% \end{macrocode}
% \end{macro}
@@ -3222,28 +3595,10 @@
\@@_cmd_if_internal:TF
{
\int_compare:nNnTF {#1} = { 3 }
- {
- \@@_scan_something_internal:n { 3 }
- \int_case:nnF \g_@@_val_level_int
- {
- { 0 } { \@@_scan_dim_unit:nN {#1} #2 }
- { 3 } { }
- }
- {
- \msg_error:nn { unravel } { incompatible-units }
- % ^^A todo: error recovery
- }
- }
- {
- \@@_scan_something_internal:n { 1 }
- \int_case:nnF \g_@@_val_level_int
- {
- { 0 } { \@@_scan_dim_unit:nN {#1} #2 }
- { 3 } % ^^A todo: error recovery
- { \msg_error:nn { unravel } { incompatible-units } }
- }
- { }
- }
+ { \@@_scan_something_internal:n { 3 } }
+ { \@@_scan_something_internal:n { 1 } }
+ \int_compare:nNnT \g_@@_val_level_int = { 0 }
+ { \@@_scan_dim_unit:nN {#1} #2 }
}
{ \@@_scan_dimen_char:nN {#1} #2 }
\seq_gpop_right:NN \g_@@_prev_input_seq \l_@@_head_tl
@@ -3283,7 +3638,7 @@
{
\bool_if:NT #2
{
- \@@_scan_keyword:nT { fF iI lL }
+ \@@_scan_keyword:nT { fFiIlL }
{
\@@_scan_inf_unit_loop:
\@@_break:w
@@ -3302,25 +3657,26 @@
{ \@@_back_input: }
\int_compare:nNnT {#1} = { 3 }
{
- \@@_scan_keyword:nT { mM uU } { \@@_break:w }
+ \@@_scan_keyword:nT { mMuU } { \@@_break:w }
\msg_error:nn { unravel } { missing-mudim }
\@@_break:w
}
- \@@_scan_keyword:nT { eE mM } { \@@_break:w }
- \@@_scan_keyword:nT { eE xX } { \@@_break:w }
- \@@_scan_keyword:nT { pP xX } { \@@_break:w }
- \@@_scan_keyword:n { tT rR uU eE }
- \@@_scan_keyword:nT { pP tT } { \@@_break:w }
- \@@_scan_keyword:nT { iI nN } { \@@_break:w }
- \@@_scan_keyword:nT { pP cC } { \@@_break:w }
- \@@_scan_keyword:nT { cC mM } { \@@_break:w }
- \@@_scan_keyword:nT { mM mM } { \@@_break:w }
- \@@_scan_keyword:nT { bB pP } { \@@_break:w }
- \@@_scan_keyword:nT { dD dD } { \@@_break:w }
- \@@_scan_keyword:nT { cC cC } { \@@_break:w }
- \@@_scan_keyword:nT { nN dD } { \@@_break:w }
- \@@_scan_keyword:nT { nN cC } { \@@_break:w }
- \@@_scan_keyword:nT { sS pP } { \@@_break:w }
+ \@@_scan_keyword:nT { eEmM } { \@@_break:w }
+ \@@_scan_keyword:nT { eExX } { \@@_break:w }
+ \@@_scan_keyword:nT { pPxX } { \@@_break:w }
+ \@@_scan_keyword:nT { tTrRuUeE }
+ { \@@_prepare_mag: }
+ \@@_scan_keyword:nT { pPtT } { \@@_break:w }
+ \@@_scan_keyword:nT { iInN } { \@@_break:w }
+ \@@_scan_keyword:nT { pPcC } { \@@_break:w }
+ \@@_scan_keyword:nT { cCmM } { \@@_break:w }
+ \@@_scan_keyword:nT { mMmM } { \@@_break:w }
+ \@@_scan_keyword:nT { bBpP } { \@@_break:w }
+ \@@_scan_keyword:nT { dDdD } { \@@_break:w }
+ \@@_scan_keyword:nT { cCcC } { \@@_break:w }
+ \@@_scan_keyword:nT { nNdD } { \@@_break:w }
+ \@@_scan_keyword:nT { nNcC } { \@@_break:w }
+ \@@_scan_keyword:nT { sSpP } { \@@_break:w }
\@@_break_point:
}
\cs_new_protected_nopar:Npn \@@_scan_inf_unit_loop:
@@ -3367,20 +3723,17 @@
\int_case:nnF \g_@@_val_level_int
{
{ 0 } { \@@_scan_dimen:nN {#1} \c_false_bool }
- {#1} { \@@_break:w }
- }
- {
- \int_compare:nNnF { \g_@@_val_level_int + #1 } = 3
- { \msg_error:nn { unravel } { incompatible-units } }
+ { 1 } { }
}
+ { \@@_break:w }
}
{ \@@_back_input: \@@_scan_dimen:nN {#1} \c_false_bool }
\@@_prev_input_join_get:nN {#1} \l_@@_tmpa_tl
\seq_gput_right:Nn \g_@@_prev_input_seq { }
\seq_gput_right:NV \g_@@_prev_input_seq \l_@@_tmpa_tl
- \@@_scan_keyword:nT { pP lL uU sS }
+ \@@_scan_keyword:nT { pPlLuUsS }
{ \@@_scan_dimen:nN {#1} \c_true_bool }
- \@@_scan_keyword:nT { mM iI nN uU sS }
+ \@@_scan_keyword:nT { mMiInNuUsS }
{ \@@_scan_dimen:nN {#1} \c_true_bool }
\@@_break_point:
\@@_prev_input_join_get:nN {#1} \l_@@_tmpa_tl
@@ -3654,9 +4007,9 @@
% \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_scan_spec:
{
- \@@_scan_keyword:nTF { tT oO } { \@@_scan_normal_dimen: }
+ \@@_scan_keyword:nTF { tToO } { \@@_scan_normal_dimen: }
{
- \@@_scan_keyword:nT { sS pP rR eE aA dD }
+ \@@_scan_keyword:nT { sSpPrReEaAdD }
{ \@@_scan_normal_dimen: }
}
\@@_scan_left_brace:
@@ -3742,11 +4095,7 @@
{ 3 } % vsplit
{
\@@_scan_int:
- \@@_scan_keyword:nF { tT oO }
- {
- \msg_error:nn { unravel } { missing-to }
- \@@_prev_input:n { to }
- }
+ \@@_scan_to:
\@@_scan_normal_dimen:
}
}
@@ -3760,14 +4109,18 @@
% For leaders, we need to fetch a glue. In all cases, retrieve the
% box construction (such as |\raise3pt\vsplit7to5em|). Finally, let
% \TeX{} run the code and print what we have done.
+% In the case of \tn{shipout}, check that \tn{mag} has a value
+% between $1$ and $32768$.
% \begin{macrocode}
\cs_new_protected:Npn \@@_do_simple_box:N #1
{
\bool_if:NTF #1 { \@@_do_leaders_fetch_skip: }
{
\seq_gpop_right:NN \g_@@_prev_input_seq \l_@@_head_tl
+ \tl_if_head_eq_meaning:VNT \l_@@_head_tl \tex_shipout:D
+ { \@@_prepare_mag: }
\tl_use:N \l_@@_head_tl \scan_stop:
- \gtl_put_right:NV \g_@@_output_gtl \l_@@_head_tl
+ \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
\@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
}
}
@@ -3812,8 +4165,8 @@
% is such that all that material is collected and put into the input
% that we will study.
% We must remember to find a glue for leaders, and for this
-% we use a stack of booleans: the top is true if the innermost box is
-% part of leaders.
+% we use a stack of letters |v|, |h| for vertical/horizontal
+% leaders, and |Z| for normal boxes.
% \begin{macrocode}
\cs_new_protected:Npn \@@_do_box_explicit:N #1
{
@@ -3838,6 +4191,10 @@
%
% \begin{macro}[aux]{\@@_box_hook:N}
% \begin{macro}[aux]{\@@_box_hook:w, \@@_box_hook_end:}
+% Used to capture the contents of an \tn{everyhbox} or similar,
+% without altering \tn{everyhbox} too much (just add one token at the
+% start). The various \texttt{o}-expansions remove
+% \cs{prg_do_nothing:}, used to avoid losing braces.
% \begin{macrocode}
\cs_new_protected:Npn \@@_box_hook:N #1
{
@@ -3855,6 +4212,7 @@
{
\exp_args:No #1 {##1}
\cs_gset_eq:NN \@@_box_hook:w \prg_do_nothing:
+ \gtl_clear:N \l_@@_after_group_gtl
\@@_print_action:
\@@_back_input:o {##1}
\@@_set_action_text:x
@@ -4009,30 +4367,35 @@
% ^^A todo: implement \@@_end_disc_group:
% ^^A todo: implement \@@_end_math_choice_group:
%
-% \begin{macro}[aux]{\@@_handle_left_brace:}
+% \begin{macro}[aux]{\@@_handle_right_brace:}
% When an end-group character is sensed, the result depends on the
% current group type.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_handle_left_brace:
+\cs_new_protected_nopar:Npn \@@_handle_right_brace:
{
- \int_case:nnF \@@_currentgrouptype:
+ \int_compare:nTF { 1 <= \@@_currentgrouptype: <= 13 }
{
- { 1 } { \@@_end_simple_group: } % simple
- { 2 } { \@@_end_box_group: } % hbox
- { 3 } { \@@_end_box_group: } % adjusted_hbox
- { 4 } { \@@_end_graf: \@@_end_box_group: } % vbox
- { 5 } { \@@_end_graf: \@@_end_box_group: } % vtop
- { 6 } { \@@_end_align_group: } % align
- { 7 } { \@@_end_no_align_group: } % no_align
- { 8 } { \@@_end_output_group: } % output
- { 9 } { \@@_end_simple_group: } % math
- { 10 } { \@@_end_disc_group: } % disc
- { 11 } { \@@_end_graf: \@@_end_simple_group: } % insert
- { 12 } { \@@_end_graf: \@@_end_simple_group: } % vcenter
- { 13 } { \@@_end_math_choice_group: } % math_choice
+ \gtl_gconcat:NNN \g_@@_output_gtl
+ \g_@@_output_gtl \c_group_end_gtl
+ \@@_back_input_gtl:N \l_@@_after_group_gtl
+ \int_case:nn \@@_currentgrouptype:
+ {
+ { 1 } { \@@_end_simple_group: } % simple
+ { 2 } { \@@_end_box_group: } % hbox
+ { 3 } { \@@_end_box_group: } % adjusted_hbox
+ { 4 } { \@@_end_graf: \@@_end_box_group: } % vbox
+ { 5 } { \@@_end_graf: \@@_end_box_group: } % vtop
+ { 6 } { \@@_end_align_group: } % align
+ { 7 } { \@@_end_no_align_group: } % no_align
+ { 8 } { \@@_end_output_group: } % output
+ { 9 } { \@@_end_simple_group: } % math
+ { 10 } { \@@_end_disc_group: } % disc
+ { 11 } { \@@_end_graf: \@@_end_simple_group: } % insert
+ { 12 } { \@@_end_graf: \@@_end_simple_group: } % vcenter
+ { 13 } { \@@_end_math_choice_group: } % math_choice
+ }
}
{ % bottom_level, semi_simple, math_shift, math_left
- \@@_back_input:
\l_@@_head_token
\@@_print_action:
}
@@ -4047,8 +4410,6 @@
\cs_new_protected_nopar:Npn \@@_end_simple_group:
{
\l_@@_head_token
- \gtl_gconcat:NNN \g_@@_output_gtl
- \g_@@_output_gtl \c_group_end_gtl
\@@_print_action:
}
% \end{macrocode}
@@ -4062,13 +4423,17 @@
\cs_new_protected_nopar:Npn \@@_end_box_group:
{
\seq_pop:NN \l_@@_leaders_box_seq \l_@@_tmpa_tl
- \str_if_eq_x:nnTF \l_@@_tmpa_tl { Z }
+ \exp_args:No \@@_end_box_group_aux:n { \l_@@_tmpa_tl }
+ }
+\cs_new_protected:Npn \@@_end_box_group_aux:n #1
+ {
+ \str_if_eq_x:nnTF {#1} { Z }
{ \@@_end_simple_group: }
{
\@@_get_x_non_relax:
\@@_set_cmd:
\int_compare:nNnTF \l_@@_head_cmd_int
- = { \@@_tex_use:n { \l_@@_tmpa_tl skip } }
+ = { \@@_tex_use:n { #1 skip } }
{
\tl_put_left:Nn \l_@@_head_tl { \c_group_end_token }
\@@_do_append_glue:
@@ -4191,6 +4556,7 @@
\mode_if_inner:TF
{
\gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+ \@@_back_input_gtl:N \l_@@_after_group_gtl
$ % $
}
{
@@ -4204,6 +4570,7 @@
\msg_error:nn { unravel } { missing-dollar }
}
\gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+ \@@_back_input_gtl:N \l_@@_after_group_gtl
$ $
}
\@@_print_action:
@@ -4221,7 +4588,7 @@
{
\@@_set_action_text:
\bool_if:NT \g_@@_internal_debug_bool
- { \iow_term:x { Cmd:~\int_use:N \l_@@_head_cmd_int } }
+ { \iow_term:x { Cmd:~\int_to_arabic:n { \l_@@_head_cmd_int } } }
\cs_if_exist_use:cF
{ @@_cmd_ \int_use:N \l_@@_head_cmd_int : }
{ \msg_error:nnx { unravel } { internal } { unknown-command } }
@@ -4267,7 +4634,7 @@
% \end{macrocode}
%
% Begin-group characters are sent to the output, as their grouping
-% behaviour may affect the scope of font changes, for instance. The are
+% behaviour may affect the scope of font changes, for instance. They are
% also performed.
% \begin{macrocode}
\@@_new_tex_cmd:nn { begin-group_char } % 1
@@ -4276,12 +4643,13 @@
\g_@@_output_gtl \c_group_begin_gtl
\@@_print_action:
\l_@@_head_token
+ \gtl_clear:N \l_@@_after_group_gtl
}
% \end{macrocode}
%
% \begin{macrocode}
\@@_new_tex_cmd:nn { end-group_char } % 2
- { \@@_handle_left_brace: }
+ { \@@_handle_right_brace: }
% \end{macrocode}
%
% Math shift characters quit vertical mode, and start math mode.
@@ -4436,6 +4804,7 @@
}
% \end{macrocode}
%
+% ^^A todo: \dump only at bottom-level (\currentgrouptype=0)
% \begin{macrocode}
\@@_new_tex_cmd:nn { stop } % 14
{
@@ -4865,9 +5234,33 @@
}
% \end{macrocode}
%
+% Save the next token at the end of \cs{l_@@_after_group_gtl}, unless
+% we are at the bottom group level, in which case, the token is ignored
+% completely.
% \begin{macrocode}
\@@_new_tex_cmd:nn { after_group } % 41
- { \msg_error:nnx { unravel } { not-implemented } { aftergroup } }
+ {
+ \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_head_tl
+ \@@_get_next:
+ \int_compare:nNnTF \@@_currentgrouptype: = \c_zero
+ {
+ \@@_print_action:x
+ {
+ Aftergroup~(level~0~=>~dropped):~
+ \tl_to_str:N \l_@@_tmpa_tl
+ \gtl_to_str:N \l_@@_head_gtl
+ }
+ }
+ {
+ \gtl_concat:NNN \l_@@_after_group_gtl
+ \l_@@_after_group_gtl \l_@@_head_gtl
+ \@@_print_action:x
+ {
+ Aftergroup:~\tl_to_str:N \l_@@_tmpa_tl
+ \gtl_to_str:N \l_@@_head_gtl
+ }
+ }
+ }
% \end{macrocode}
%
% See \cs{@@_do_append_glue:}.
@@ -5124,19 +5517,20 @@
}
% \end{macrocode}
%
-% ^^A todo: take \aftergroup into account
% \begin{macrocode}
\@@_new_tex_cmd:nn { begin_group } % 61
{
\gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
- \@@_print_action:
\l_@@_head_token
+ \gtl_clear:N \l_@@_after_group_gtl
+ \@@_print_action:
}
\@@_new_tex_cmd:nn { end_group } % 62
{
\gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
- \@@_print_action:
+ \@@_back_input_gtl:N \l_@@_after_group_gtl
\l_@@_head_token
+ \@@_print_action:
}
% \end{macrocode}
%
@@ -5245,24 +5639,24 @@
}
{ 6 } % pdfliteral
{
- \@@_scan_keyword:nF { dD iI rR eE cC tT }
- { \@@_scan_keyword:n { pP aA gG eE } }
+ \@@_scan_keyword:nF { dDiIrReEcCtT }
+ { \@@_scan_keyword:n { pPaAgGeE } }
\@@_scan_pdf_ext_toks:
}
{ 7 } % pdfobj
{
\@@_scan_keyword:nTF
- { rR eE sS eE rR vV eE oO bB jJ nN uU mM }
+ { rReEsSeErRvVeEoObBjJnNuUmM }
{ \@@_skip_optional_space: }
{
- \@@_scan_keyword:nF { uU sS eE oO bB jJ nN uU mM }
+ \@@_scan_keyword:nF { uUsSeEoObBjJnNuUmM }
{ \@@_scan_int: }
- \@@_scan_keyword:nT { sS tT rR eE aA mM }
+ \@@_scan_keyword:nT { sStTrReEaAmM }
{
- \@@_scan_keyword:nT { aA tT tT rR }
+ \@@_scan_keyword:nT { aAtTtTrR }
{ \@@_scan_pdf_ext_toks: }
}
- \@@_scan_keyword:n { fF iI lL eE }
+ \@@_scan_keyword:n { fFiIlLeE }
\@@_scan_pdf_ext_toks:
}
}
@@ -5270,9 +5664,9 @@
{ \@@_scan_int: }
{ 9 } % pdfxform
{
- \@@_scan_keyword:nT { aA tT tT rR }
+ \@@_scan_keyword:nT { aAtTtTrR }
{ \@@_scan_pdf_ext_toks: }
- \@@_scan_keyword:nTF { rR eE sS oO uU rR cC eE sS }
+ \@@_scan_keyword:nTF { rReEsSoOuUrRcCeEsS }
{ \@@_scan_pdf_ext_toks: }
\@@_scan_int:
}
@@ -5285,10 +5679,10 @@
{ 13 } % pdfannot
{
\@@_scan_keyword:nTF
- { rR eE sS eE rR vV eE oO bB jJ nN uU mM }
+ { rReEsSeErRvVeEoObBjJnNuUmM }
{ \@@_scan_optional_space: }
{
- \@@_scan_keyword:nT { uU sS eE oO bB jJ nN uU mM }
+ \@@_scan_keyword:nT { uUsSeEoObBjJnNuUmM }
{ \@@_scan_int: }
\@@_scan_alt_rule:
\@@_scan_pdf_ext_toks:
@@ -5310,10 +5704,10 @@
}
{ 16 } % pdfoutline
{
- \@@_scan_keyword:nT { aA tT tT rR }
+ \@@_scan_keyword:nT { aAtTtTrR }
{ \@@_scan_pdf_ext_toks: }
\@@_scan_action:
- \@@_scan_keyword:nT { cC oO uU nN tT }
+ \@@_scan_keyword:nT { cCoOuUnNtT }
{ \@@_scan_int: }
\@@_scan_pdf_ext_toks:
}
@@ -5332,7 +5726,7 @@
{ 23 } % pdfcatalog
{
\@@_scan_pdf_ext_toks:
- \@@_scan_keyword:n { oO pP eE nN aA cC tT iI oO nN }
+ \@@_scan_keyword:n { oOpPeEnNaAcCtTiIoOnN }
{ \@@_scan_action: }
}
{ 24 } % pdfnames
@@ -5422,7 +5816,7 @@
\cs_new_protected_nopar:Npn \@@_scan_rule_attr:
{
\@@_scan_alt_rule:
- \@@_scan_keyword:nT { aA tT tT rR }
+ \@@_scan_keyword:nT { aAtTtTrR }
{ \@@_scan_pdf_ext_toks: }
}
% \end{macrocode}
@@ -5839,7 +6233,7 @@
\@@_scan_keyword:nTF { aAtT }
{ \@@_scan_normal_dimen: }
{
- \@@_scan_keyword:nT { sS cC aA lL eE dD }
+ \@@_scan_keyword:nT { sScCaAlLeEdD }
{ \@@_scan_int: }
}
\bool_gset_false:N \g_@@_name_in_progress_bool
@@ -5910,21 +6304,55 @@
}
% \end{macrocode}
%
+% \begin{macro}[aux, EXP]{\@@_read_to_cs_safe:nTF, \@@_read_to_cs_safe:fTF}
+% After \tn{read} or \tn{readline}, find an int, the mandatory
+% keyword |to|, and an assignable token. The \tn{read} and
+% \tn{readline} primitives throw a fatal error in \tn{nonstopmode}
+% and in \tn{batchmode} when trying to read from a stream that is
+% outside $[0,15]$ or that is not open (according to \tn{ifeof}). We
+% detect this situation using \cs{@@_read_to_cs_safe:nTF} after
+% grabbing all arguments of the primitives. If reading is unsafe,
+% let the user know that \TeX{} would have thrown a fatal error.
% \begin{macrocode}
\@@_prefixed_new:nn { read_to_cs } % 96
{
- \@@_prev_input:V \l_@@_head_tl
+ \@@_prev_input_silent:V \l_@@_head_tl
\@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
\@@_scan_int:
- \@@_scan_keyword:nF { tToO }
+ \@@_scan_to:
+ \@@_scan_r_token:
+ \seq_get_right:NN \g_@@_prev_input_seq \l_@@_tmpa_tl
+ \@@_read_to_cs_safe:fTF
+ { \@@_tl_first_int:N \l_@@_tmpa_tl }
+ { \@@_assign_token:n { } }
{
- \msg_error:nn { unravel } { missing-to }
- \@@_prev_input:n { to }
+ \seq_gpop_right:NN \g_@@_prev_input_seq \l_@@_head_tl
+ \@@_tex_fatal_error:nV { cannot-read } \l_@@_head_tl
+ }
+ }
+\prg_new_conditional:Npnn \@@_read_to_cs_safe:n #1 { TF }
+ {
+ \int_compare:nNnTF { \etex_interactionmode:D } > { 1 }
+ { \prg_return_true: }
+ {
+ \int_compare:nNnTF {#1} < { 0 }
+ { \prg_return_false: }
+ {
+ \int_compare:nNnTF {#1} > { 15 }
+ { \prg_return_false: }
+ {
+ \tex_ifeof:D #1 \exp_stop_f:
+ \prg_return_false:
+ \else:
+ \prg_return_true:
+ \fi:
+ }
+ }
}
- \@@_scan_r_token:
- \@@_assign_token:n { }
}
+\cs_generate_variant:Nn \@@_read_to_cs_safe:nTF { f }
% \end{macrocode}
+% \end{macro}
%
% \begin{macrocode}
\@@_prefixed_new:nn { def } % 97
@@ -6312,8 +6740,8 @@
\@@_scan_file_name:
\seq_gpop_right:NN \g_@@_prev_input_seq \l_@@_head_tl
\tl_set:Nx \l_@@_tmpa_tl { \tl_tail:N \l_@@_head_tl }
- \@@_tl_gset_input:Nno \g_@@_tmpc_tl { } \l_@@_tmpa_tl
- \@@_back_input:V \g_@@_tmpc_tl
+ \@@_file_get:nN \l_@@_tmpa_tl \l_@@_tmpa_tl
+ \@@_back_input:V \l_@@_tmpa_tl
\@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
}
% \end{macrocode}
@@ -6380,7 +6808,7 @@
{ 23 } \@@_scan_pdf_ext_toks:
{ 24 }
{
- \@@_scan_keyword:n { fF iI lL eE }
+ \@@_scan_keyword:n { fFiIlLeE }
\@@_scan_pdf_ext_toks:
}
{ 25 } \@@_scan_pdffiledump:
@@ -6402,23 +6830,23 @@
{ \@@_scan_int: \@@_scan_int: }
\cs_new_protected_nopar:Npn \@@_scan_pdfcolorstackinit:
{
- \@@_scan_keyword:nTF { pP aA gG eE }
+ \@@_scan_keyword:nTF { pPaAgGeE }
{ \bool_set_true:N \l_@@_tmpa_bool }
{ \bool_set_false:N \l_@@_tmpb_bool }
- \@@_scan_keyword:nF { dD iI rR eE cC tT }
- { \@@_scan_keyword:n { pP aA gG eE } }
+ \@@_scan_keyword:nF { dDiIrReEcCtT }
+ { \@@_scan_keyword:n { pPaAgGeE } }
\@@_scan_toks_to_str:
}
\cs_new_protected_nopar:Npn \@@_scan_pdffiledump:
{
- \@@_scan_keyword:nT { oO fF fF sS eE tT } \@@_scan_int:
- \@@_scan_keyword:nT { lL eE nN gG tT hH } \@@_scan_int:
+ \@@_scan_keyword:nT { oOfFfFsSeEtT } \@@_scan_int:
+ \@@_scan_keyword:nT { lLeEnNgGtThH } \@@_scan_int:
\@@_scan_pdf_ext_toks:
}
\cs_new_protected_nopar:Npn \@@_scan_pdfmatch:
{
- \@@_scan_keyword:n { iI cC aA sS eE }
- \@@_scan_keyword:nT { sS uU bB cC oO uU nN tT }
+ \@@_scan_keyword:n { iIcCaAsSeE }
+ \@@_scan_keyword:nT { sSuUbBcCoOuUnNtT }
{ \@@_scan_int: }
\@@_scan_pdf_ext_toks:
\@@_scan_pdf_ext_toks:
@@ -7040,7 +7468,7 @@
{
[=====
\bool_if:NT \g_@@_number_steps_bool
- { ~ Step ~ \int_use:N \g_@@_step_int \ }
+ { ~ Step ~ \int_to_arabic:n { \g_@@_step_int } ~ }
=====]~
\int_compare:nNnTF
{ \str_count:N \g_@@_action_text_str }
@@ -7091,12 +7519,15 @@
\cs_new_protected_nopar:Npn \@@_print_assigned_register:
{
\@@_after_assignment: % ^^A todo: simplify
- \@@_print_action:x
+ \exp_args:Nx \@@_print_action:x
{
- Set~ \exp_after:wN \token_to_str:N \l_@@_defined_tl
- \tl_if_single:NT \l_@@_defined_tl
- { ( \exp_after:wN \token_to_meaning:N \l_@@_defined_tl ) }
- = \exp_after:wN \@@_the:w \l_@@_defined_tl
+ \exp_not:n
+ {
+ Set~ \exp_after:wN \token_to_str:N \l_@@_defined_tl
+ \tl_if_single:NT \l_@@_defined_tl
+ { ( \exp_after:wN \token_to_meaning:N \l_@@_defined_tl ) }
+ }
+ = \exp_not:N \tl_to_str:n { \@@_the:w \l_@@_defined_tl }
}
\@@_omit_after_assignment:w
}
@@ -7287,6 +7718,50 @@
%
% ^^A todo: I suspect a bug if given 'a' twice in a row
%
+% \subsubsection{Errors}
+%
+% \begin{macro}[int]{\@@_tex_msg_new:nnn}
+% This stores a \TeX{} error message.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_tex_msg_new:nnn #1#2#3
+ {
+ \cs_new_nopar:cpn { @@_tex_msg_error_#1: } {#2}
+ \cs_new_nopar:cpn { @@_tex_msg_help_#1: } {#3}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_tex_error:nn, \@@_tex_error:nV}
+% Throw the |tex-error| message, with arguments: |#2| which triggered
+% the error, \TeX{}'s error message, and \TeX{}'s help text.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_tex_error:nn #1#2
+ {
+ \msg_error:nnxxx { unravel } { tex-error }
+ { \tl_to_str:n {#2} }
+ { \use:c { @@_tex_msg_error_#1: } }
+ { \use:c { @@_tex_msg_help_#1: } }
+ }
+\cs_generate_variant:Nn \@@_tex_error:nn { nV }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_tex_fatal_error:nn, \@@_tex_fatal_error:nV}
+% Throw the |tex-fatal| error message, with arguments: |#2| which
+% triggered the fatal error, \TeX{}'s error message, and \TeX{}'s
+% help text.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_tex_fatal_error:nn #1#2
+ {
+ \msg_error:nnxxx { unravel } { tex-fatal }
+ { \tl_to_str:n {#2} }
+ { \use:c { @@_tex_msg_error_#1: } }
+ { \use:c { @@_tex_msg_help_#1: } }
+ }
+\cs_generate_variant:Nn \@@_tex_fatal_error:nn { nV }
+% \end{macrocode}
+% \end{macro}
+%
% \subsection{Keys}
%
% Each key needs to be defined twice: for its default setting and for
@@ -7426,6 +7901,7 @@
\gtl_gclear:N \g_@@_after_assignment_gtl
\bool_gset_true:N \g_@@_set_box_allowed_bool
\bool_gset_false:N \g_@@_name_in_progress_bool
+ \gtl_clear:N \l_@@_after_group_gtl
}
% \end{macrocode}
% \end{macro}
@@ -7486,8 +7962,6 @@
{ Missing~font~identifier.~\iow_char:N\\nullfont~inserted. }
\msg_new:nnn { unravel } { missing-rparen }
{ Missing~right~parenthesis~inserted~for~expression. }
-\msg_new:nnn { unravel } { incompatible-units }
- { Mu~glue/dimen~used~as~a~normal~glue/dimen~or~vice-versa. }
\msg_new:nnn { unravel } { missing-mudim }
{ Missing~mu~unit. }
\msg_new:nnn { unravel } { missing-cs }
@@ -7544,6 +8018,63 @@
{ The~following~feature~is~not~implemented:~'#1'. }
\msg_new:nnn { unravel } { endinput-ignored }
{ The~primitive~\iow_char:N\\endinput~was~ignored. }
+\msg_new:nnn { unravel } { missing-something }
+ { Something~is~missing,~sorry! }
+\msg_new:nnnn { unravel } { tex-error }
+ { TeX~sees~"#1"~and~throws~an~error:\\\\ \iow_indent:n {#2} }
+ {
+ \tl_if_empty:nTF {#3}
+ { TeX~provides~no~further~help~for~this~error. }
+ { TeX's~advice~is:\\\\ \iow_indent:n {#3} }
+ }
+\msg_new:nnnn { unravel } { tex-fatal }
+ { TeX~sees~"#1"~and~throws~a~fatal~error:\\\\ \iow_indent:n {#2} }
+ {
+ \tl_if_empty:nTF {#3}
+ { TeX~provides~no~further~help~for~this~error. }
+ { TeX's~advice~is:\\\\ \iow_indent:n {#3} }
+ }
+% \end{macrocode}
+%
+% Some error messages from \TeX{} itself.
+% \begin{macrocode}
+\@@_tex_msg_new:nnn { incompatible-mag }
+ {
+ Incompatible~magnification~
+ ( \int_to_arabic:n { \@@_mag: } ); \\
+ \ the~previous~value~will~be~retained
+ }
+ {
+ I~can~handle~only~one~magnification~ratio~per~job.~So~I've\\
+ reverted~to~the~magnification~you~used~earlier~on~this~run.
+ }
+\@@_tex_msg_new:nnn { illegal-mag }
+ {
+ Illegal~magnification~has~been~changed~to~1000~
+ ( \int_to_arabic:n { \@@_mag: } )
+ }
+ { The~magnification~ratio~must~be~between~1~and~32768. }
+\@@_tex_msg_new:nnn { incompatible-units }
+ { Incompatible~glue~units }
+ { I'm~going~to~assume~that~1mu=1pt~when~they're~mixed. }
+% \end{macrocode}
+%
+% Fatal \TeX{} error messages.
+% \begin{macrocode}
+\@@_tex_msg_new:nnn { cannot-read }
+ { ***~(cannot~\iow_char:N\\read~from~terminal~in~nonstop~modes) }
+ { }
+\@@_tex_msg_new:nnn { file-error }
+ { ***~(job~aborted,~file~error~in~nonstop~mode) }
+ { }
+\@@_tex_msg_new:nnn { interwoven-preambles }
+ { (interwoven~alignment~preambles~are~not~allowed) }
+ { }
+% \end{macrocode}
+%
+% Restore catcodes to their original values.
+% \begin{macrocode}
+\@@_setup_restore:
% \end{macrocode}
%
% \begin{macrocode}