texlive[59175] Master/texmf-dist: unravel (12may21)

commits+karl at tug.org commits+karl at tug.org
Wed May 12 22:04:18 CEST 2021


Revision: 59175
          http://tug.org/svn/texlive?view=revision&revision=59175
Author:   karl
Date:     2021-05-12 22:04:18 +0200 (Wed, 12 May 2021)
Log Message:
-----------
unravel (12may21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/unravel/unravel.pdf
    trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx
    trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty

Modified: trunk/Master/texmf-dist/doc/latex/unravel/unravel.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx	2021-05-12 20:02:13 UTC (rev 59174)
+++ trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx	2021-05-12 20:04:18 UTC (rev 59175)
@@ -1,5 +1,5 @@
 % \iffalse
-%% File: unravel.dtx Copyright (C) 2013, 2015, 2018-2019 Bruno Le Floch
+%% File: unravel.dtx Copyright (C) 2013, 2015, 2018-2019, 2021 Bruno Le Floch
 %%
 %% It may be distributed and/or modified under the conditions of the
 %% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -23,9 +23,9 @@
 %
 % \title{The \textsf{unravel} package: \\
 %   watching TeX digest tokens\thanks{This
-%     file has version number 0.2h, last revised 2019/11/15.}}
+%     file has version number 0.3a, last revised 2021/05/11.}}
 % \author{Bruno Le Floch}
-% \date{2019/11/15}
+% \date{2021/05/11}
 %
 % \maketitle
 % \tableofcontents
@@ -254,15 +254,15 @@
 %   incorrect widths.
 % \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
-%   \tn{pdfprimitive}, \tn{discretionary}, as well as
-%   all primitives specific to engines other than \pdfTeX{}.
+%   \tn{cr}, \tn{crcr},~|&|), some math mode primitives, and
+%   \tn{pdfprimitive}, as well as
+%   many primitives specific to engines other than \pdfTeX{}.
 %   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{lastpenalty}, \tn{lastskip}, \tn{currentifbranch}
+%   may have wrong values.  Perhaps
 %   \tn{currentgrouplevel} and \tn{currentgrouptype} too.
 % \item Setting \tn{globaldefs} to a non-zero value may cause problems.
 % \item Tokens passed to \tn{aftergroup} are lost when \pkg{unravel} is
@@ -288,7 +288,6 @@
 % \subsection{Future perhaps}
 %
 % \begin{itemize}
-% \item Allow to replay steps that have already been run.
 % \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
@@ -295,8 +294,6 @@
 %   \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}
@@ -538,7 +535,7 @@
 % \cs{str_range:nnn}.  Otherwise loading \pkg{l3str} would give
 % an error.
 %    \begin{macrocode}
-\RequirePackage{expl3,xparse}[2018/02/21]
+\RequirePackage{expl3,xparse}[2021/01/01]
 \RequirePackage{gtl}[2018/12/28]
 \csname cs_if_exist:cF\endcsname{str_range:nnn}{\RequirePackage{l3str}}
 %    \end{macrocode}
@@ -557,7 +554,7 @@
   {%
     \csname @@_setup_restore:\endcsname
     \ProvidesExplPackage
-      {unravel} {2019/11/15} {0.2h} {Watching TeX digest tokens}%
+      {unravel} {2021/05/11} {0.3a} {Watching TeX digest tokens}%
     \csname @@_setup_unravel:\endcsname
   }%
 %    \end{macrocode}
@@ -564,6 +561,20 @@
 %
 % \subsection{Primitives, variants, and helpers}
 %
+% \subsubsection{Adjustments to \pkg{expl3}}
+%
+% In upcoming versions of \pkg{expl3}, the \cs{group_align_safe_begin:}
+% and \cs{group_align_safe_end:} commands may involve an explicit
+% end-group character token with non-standard character code, which
+% would wrongly be normalized by \pkg{gtl} (used by \pkg{unravel}),
+% hence break.  To avoid this we change here the definitions slightly.
+%    \begin{macrocode}
+\cs_gset:Npn \group_align_safe_begin:
+  { \exp:w \if_false: { \fi: -`} \exp_stop_f: }
+\cs_gset:Npn \group_align_safe_end:
+  { \if_int_compare:w `{ = \c_zero_int } \fi: }
+%    \end{macrocode}
+%
 % \subsubsection{Renamed primitives}
 %
 % \begin{macro}
@@ -621,6 +632,7 @@
 \cs_generate_variant:Nn \tl_to_str:n { o }
 \cs_generate_variant:Nn \tl_if_eq:nnTF { o }
 \cs_generate_variant:Nn \tl_if_head_eq_meaning:nNT { V }
+\cs_generate_variant:Nn \tl_if_head_eq_meaning:nNTF { V }
 \cs_generate_variant:Nn \tl_if_single_token:nT { V }
 \cs_generate_variant:Nn \gtl_gput_right:Nn { NV }
 \cs_generate_variant:Nn \gtl_if_empty:NTF { c }
@@ -746,28 +758,42 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}{\@@_prepare_mag:}
-%   Used whenever \TeX{} needs the value of \tn{mag}.  ^^A todo: move
+% \begin{macro}[EXP]{\@@_use_ii_i:nn}
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_prepare_mag:
+\cs_new:Npn \@@_use_ii_i:nn #1#2 { #2 #1 }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_prompt_input:Nn}
+% \begin{macro}[rEXP]{\@@_prompt_input:w}
+% \begin{macro}[EXP]{\@@_prompt_input_aux:w, \@@_use_none_delimit_by_q_recursion_tail:w}
+% \begin{variable}{\q_@@_recursion_tail}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_prompt_input:Nn #1#2
   {
-    \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:
+    \clist_gset:Nx #1
+      { \@@_prompt_input:w \prg_do_nothing: #2 , \q_@@_recursion_tail , }
   }
+\cs_new:Npn \@@_prompt_input:w #1 ,
+  {
+    \tl_trim_spaces_apply:oN {#1} \@@_use_ii_i:nn
+    \@@_prompt_input_aux:w ,
+  }
+\cs_new:Npn \@@_prompt_input_aux:w #1 ,
+  {
+    \@@_use_none_delimit_by_q_recursion_tail:w #1
+      \use_none:nnnnn \q_@@_recursion_tail
+    { \tl_to_str:n {#1} } ,
+    \@@_prompt_input:w \prg_do_nothing:
+  }
+\cs_new:Npn \@@_use_none_delimit_by_q_recursion_tail:w
+    #1 \q_@@_recursion_tail { }
+\quark_new:N \q_@@_recursion_tail
 %    \end{macrocode}
+% \end{variable}
 % \end{macro}
+% \end{macro}
+% \end{macro}
 %
 % \subsubsection{String helpers}
 %
@@ -801,34 +827,19 @@
 % \end{macro}
 % \end{macro}
 %
-% ^^A todo: change approach: this abuses future l3obj.
-% \begin{macro}[EXP]{\@@_to_str:n}
-% \begin{macro}[EXP]
-%   {\@@_to_str_auxi:w, \@@_to_str_auxii:w, \@@_gtl_to_str:n}
+% \begin{macro}[EXP]{\@@_to_str:Nn}
 %   Use the type-appropriate conversion to string.
 %    \begin{macrocode}
-\cs_new:Npn \@@_to_str:n #1
+\cs_new:Npn \@@_to_str:Nn #1
   {
-    \tl_if_head_eq_meaning:nNTF {#1} \scan_stop:
-      { \@@_to_str_auxi:w #1 ? \q_stop }
-      { \tl_to_str:n }
-    {#1}
+    \if_meaning:w T #1
+      \exp_after:wN \tl_to_str:n
+    \else:
+      \exp_after:wN \gtl_to_str:n
+    \fi:
   }
-\cs_set:Npn \@@_tmp:w #1
-  {
-    \cs_new:Npn \@@_to_str_auxi:w ##1##2 \q_stop
-      {
-        \exp_after:wN \@@_to_str_auxii:w \token_to_str:N ##1 \q_mark
-          #1 tl \q_mark \q_stop
-      }
-    \cs_new:Npn \@@_to_str_auxii:w ##1 #1 ##2 \q_mark ##3 \q_stop
-      { \cs_if_exist_use:cF { @@_ ##2 _to_str:n } { \tl_to_str:n } }
-  }
-\exp_args:No \@@_tmp:w { \tl_to_str:n { s _ _ } }
-\cs_new:Npn \@@_gtl_to_str:n { \gtl_to_str:n }
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
 %
 % \begin{macro}{\@@_str_truncate_left:nn}
 % \begin{macro}{\@@_str_truncate_left_aux:nnn}
@@ -922,6 +933,23 @@
 %
 % \subsubsection{Helpers concerning tokens}
 %
+% \begin{macro}{\@@_active_do:nn}
+%   Apply some code to an active character token constructed from its
+%   character code.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_active_do:nn #1#2
+  {
+    \group_begin:
+    \char_set_active_eq:nN {#1} \scan_stop:
+    \use:x
+      {
+        \group_end:
+        \exp_not:n {#2} { \char_generate:nn {#1} { 13 } }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\@@_token_to_char:N}
 % \begin{macro}{\@@_meaning_to_char:n, \@@_meaning_to_char:o}
 % \begin{macro}
@@ -1068,7 +1096,9 @@
 %
 % \subsubsection{Helpers for previous input}
 %
-% \begin{macro}[EXP]{\@@_prev_input_count:, \@@_prev_input_count_aux:n}
+% \begin{macro}[EXP]{\@@_prev_input_count:, \@@_prev_input_count_aux:n, \@@_prev_input_count_aux:Nn}
+%   Count prev input levels, skipping empty ones (of either tl or gtl
+%   type).
 %    \begin{macrocode}
 \cs_new:Npn \@@_prev_input_count:
   {
@@ -1080,38 +1110,74 @@
       }
   }
 \cs_new:Npn \@@_prev_input_count_aux:n #1
-  { \tl_if_empty:nF {#1} { + 1 } }
+  { \@@_prev_input_count_aux:Nn #1 }
+\cs_new:Npn \@@_prev_input_count_aux:Nn #1#2
+  {
+    \if_meaning:w T #1
+      \exp_after:wN \tl_if_empty:nF
+    \else:
+      \exp_after:wN \str_if_eq:onF \exp_after:wN \c_empty_gtl
+    \fi:
+    {#2} { + 1 }
+  }
 %    \end{macrocode}
 % \end{macro}
 %
 % \begin{macro}
 %   {
-%     \@@_prev_input_get:N,
 %     \@@_prev_input_gpush:,
 %     \@@_prev_input_gpush:N,
-%     \@@_prev_input_gpop:N,
 %     \@@_prev_input_gpush_gtl:,
 %     \@@_prev_input_gpush_gtl:N,
-%     \@@_prev_input_gpop_gtl:N,
+%     \@@_prev_input_gpush_aux:NN
 %   }
-% ^^A todo: doc and add optional sanity checking
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_prev_input_get:N
-  { \seq_get_right:NN \g_@@_prev_input_seq }
 \cs_new_protected:Npn \@@_prev_input_gpush:
-  { \seq_gput_right:Nn \g_@@_prev_input_seq { } }
+  { \seq_gput_right:Nn \g_@@_prev_input_seq { T { } } }
 \cs_new_protected:Npn \@@_prev_input_gpush:N
-  { \seq_gput_right:NV \g_@@_prev_input_seq }
-\cs_new_protected:Npn \@@_prev_input_gpop:N
-  { \seq_gpop_right:NN \g_@@_prev_input_seq }
+  { \@@_prev_input_gpush_aux:NN T }
 \cs_new_protected:Npn \@@_prev_input_gpush_gtl:
-  { \seq_gput_right:NV \g_@@_prev_input_seq \c_empty_gtl }
+  { \@@_prev_input_gpush_gtl:N \c_empty_gtl }
 \cs_new_protected:Npn \@@_prev_input_gpush_gtl:N
-  { \seq_gput_right:NV \g_@@_prev_input_seq }
+  { \@@_prev_input_gpush_aux:NN G }
+\cs_new_protected:Npn \@@_prev_input_gpush_aux:NN #1#2
+  { \seq_gput_right:Nx \g_@@_prev_input_seq { #1 { \exp_not:o {#2} } } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_prev_aux_tl}
+% \begin{macro}
+%   {
+%     \@@_prev_input_get:N,
+%     \@@_prev_input_gpop:N,
+%     \@@_prev_input_gpop_gtl:N,
+%     \@@_prev_input_aux:NNN,
+%     \@@_prev_input_aux:NNNn,
+%   }
+%    \begin{macrocode}
+\tl_new:N \l_@@_prev_aux_tl
+\cs_new_protected:Npn \@@_prev_input_get:N
+  { \@@_prev_input_aux:NNN \seq_get_right:NN T }
+\cs_new_protected:Npn \@@_prev_input_gpop:N
+  { \@@_prev_input_aux:NNN \seq_gpop_right:NN T }
 \cs_new_protected:Npn \@@_prev_input_gpop_gtl:N
-  { \seq_gpop_right:NN \g_@@_prev_input_seq }
+  { \@@_prev_input_aux:NNN \seq_gpop_right:NN G }
+\cs_new_protected:Npn \@@_prev_input_aux:NNN #1#2#3
+  {
+    #1 \g_@@_prev_input_seq \l_@@_prev_aux_tl
+    \exp_after:wN \@@_prev_input_aux:NNNn
+    \exp_after:wN #2 \exp_after:wN #3 \l_@@_prev_aux_tl
+  }
+\cs_new_protected:Npn \@@_prev_input_aux:NNNn #1#2#3
+  {
+    \token_if_eq_meaning:NNTF #1#3
+      { \tl_set:Nn }
+      { \msg_error:nnnnnn { unravel } { prev-input } {#1} {#3} }
+    #2
+  }
 %    \end{macrocode}
 % \end{macro}
+% \end{variable}
 %
 % \begin{macro}
 %   {
@@ -1430,6 +1496,13 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{variable}{\g_@@_lastnamedcs_tl}
+%   Used for \LuaTeX{}'s \tn{lastnamedcs} primitive.
+%    \begin{macrocode}
+\tl_new:N \g_@@_lastnamedcs_tl
+%    \end{macrocode}
+% \end{variable}
+%
 % \begin{variable}
 %   {
 %     \g_@@_after_assignment_gtl,
@@ -1469,7 +1542,7 @@
 %
 % \begin{variable}{\g_@@_val_level_int}
 %   See \TeX{}'s |cur_val_level| variable.  This is set by
-%   \cs{@@_scan_something_internal:n} to
+%   \cs{@@_rescan_something_internal:n} to
 %   \begin{itemize}
 %   \item $0$ for integer values,
 %   \item $1$ for dimension values,
@@ -1568,6 +1641,29 @@
 %    \end{macrocode}
 % \end{variable}
 %
+% \begin{macro}{\@@_prepare_mag:}
+%   Used whenever \TeX{} needs the value of \tn{mag}.
+%    \begin{macrocode}
+\cs_new_protected: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}
+%
 % \subsection{Numeric codes}
 % \label{sec:numeric-codes}
 %
@@ -1586,7 +1682,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}{\@@_tex_primitive:nnn}
+% \begin{macro}{\@@_tex_primitive:nnn, \@@_tex_primitive_pdf:nnn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_tex_primitive:nnn #1#2#3
   {
@@ -1593,6 +1689,12 @@
     \tl_const:cx { c_@@_tex_#1_tl }
       { { \@@_tex_use:n {#2} } {#3} }
   }
+\cs_new_protected:Npn \@@_tex_primitive_pdf:nnn #1#2#3
+  {
+    \sys_if_engine_pdftex:F
+      { \@@_tex_primitive:nnn {#1} {#2} {#3} }
+    \@@_tex_primitive:nnn { pdf #1 } {#2} {#3}
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -1850,6 +1952,11 @@
 \@@_tex_primitive:nnn { /                 } { ital_corr } { 0 }
 \@@_tex_primitive:nnn { accent            } { accent } { 0 }
 \@@_tex_primitive:nnn { mathaccent        } { math_accent } { 0 }
+\sys_if_engine_luatex:T
+  {
+    \@@_tex_primitive:nnn
+      { explicitdiscretionary } { discretionary } { 1 }
+  }
 \@@_tex_primitive:nnn { -                 } { discretionary } { 1 }
 \@@_tex_primitive:nnn { discretionary     } { discretionary } { 0 }
 \@@_tex_primitive:nnn { eqno              } { eq_no } { 0 }
@@ -1893,42 +2000,42 @@
 \@@_tex_primitive:nnn { special           } { extension } { 3 }
 \@@_tex_primitive:nnn { immediate         } { extension } { 4 }
 \@@_tex_primitive:nnn { setlanguage       } { extension } { 5 }
-\@@_tex_primitive:nnn { pdfliteral        } { extension } { 6 }
-\@@_tex_primitive:nnn { pdfobj            } { extension } { 7 }
-\@@_tex_primitive:nnn { pdfrefobj         } { extension } { 8 }
-\@@_tex_primitive:nnn { pdfxform          } { extension } { 9 }
-\@@_tex_primitive:nnn { pdfrefxform       } { extension } { 10 }
-\@@_tex_primitive:nnn { pdfximage         } { extension } { 11 }
-\@@_tex_primitive:nnn { pdfrefximage      } { extension } { 12 }
-\@@_tex_primitive:nnn { pdfannot          } { extension } { 13 }
-\@@_tex_primitive:nnn { pdfstartlink      } { extension } { 14 }
-\@@_tex_primitive:nnn { pdfendlink        } { extension } { 15 }
-\@@_tex_primitive:nnn { pdfoutline        } { extension } { 16 }
-\@@_tex_primitive:nnn { pdfdest           } { extension } { 17 }
-\@@_tex_primitive:nnn { pdfthread         } { extension } { 18 }
-\@@_tex_primitive:nnn { pdfstartthread    } { extension } { 19 }
-\@@_tex_primitive:nnn { pdfendthread      } { extension } { 20 }
-\@@_tex_primitive:nnn { pdfsavepos        } { extension } { 21 }
-\@@_tex_primitive:nnn { pdfinfo           } { extension } { 22 }
-\@@_tex_primitive:nnn { pdfcatalog        } { extension } { 23 }
-\@@_tex_primitive:nnn { pdfnames          } { extension } { 24 }
-\@@_tex_primitive:nnn { pdffontattr       } { extension } { 25 }
-\@@_tex_primitive:nnn { pdfincludechars   } { extension } { 26 }
-\@@_tex_primitive:nnn { pdfmapfile        } { extension } { 27 }
-\@@_tex_primitive:nnn { pdfmapline        } { extension } { 28 }
-\@@_tex_primitive:nnn { pdftrailer        } { extension } { 29 }
-\@@_tex_primitive:nnn { pdfresettimer     } { extension } { 30 }
-\@@_tex_primitive:nnn { pdffontexpand     } { extension } { 31 }
-\@@_tex_primitive:nnn { pdfsetrandomseed  } { extension } { 32 }
-\@@_tex_primitive:nnn { pdfsnaprefpoint   } { extension } { 33 }
-\@@_tex_primitive:nnn { pdfsnapy          } { extension } { 34 }
-\@@_tex_primitive:nnn { pdfsnapycomp      } { extension } { 35 }
-\@@_tex_primitive:nnn { pdfglyphtounicode } { extension } { 36 }
-\@@_tex_primitive:nnn { pdfcolorstack     } { extension } { 37 }
-\@@_tex_primitive:nnn { pdfsetmatrix      } { extension } { 38 }
-\@@_tex_primitive:nnn { pdfsave           } { extension } { 39 }
-\@@_tex_primitive:nnn { pdfrestore        } { extension } { 40 }
-\@@_tex_primitive:nnn { pdfnobuiltintounicode } { extension } { 41 }
+\@@_tex_primitive_pdf:nnn { literal       } { extension } { 6 }
+\@@_tex_primitive_pdf:nnn { obj           } { extension } { 7 }
+\@@_tex_primitive_pdf:nnn { refobj        } { extension } { 8 }
+\@@_tex_primitive_pdf:nnn { xform         } { extension } { 9 }
+\@@_tex_primitive_pdf:nnn { refxform      } { extension } { 10 }
+\@@_tex_primitive_pdf:nnn { ximage        } { extension } { 11 }
+\@@_tex_primitive_pdf:nnn { refximage     } { extension } { 12 }
+\@@_tex_primitive_pdf:nnn { annot         } { extension } { 13 }
+\@@_tex_primitive_pdf:nnn { startlink     } { extension } { 14 }
+\@@_tex_primitive_pdf:nnn { endlink       } { extension } { 15 }
+\@@_tex_primitive_pdf:nnn { outline       } { extension } { 16 }
+\@@_tex_primitive_pdf:nnn { dest          } { extension } { 17 }
+\@@_tex_primitive_pdf:nnn { thread        } { extension } { 18 }
+\@@_tex_primitive_pdf:nnn { startthread   } { extension } { 19 }
+\@@_tex_primitive_pdf:nnn { endthread     } { extension } { 20 }
+\@@_tex_primitive_pdf:nnn { savepos       } { extension } { 21 }
+\@@_tex_primitive_pdf:nnn { info          } { extension } { 22 }
+\@@_tex_primitive_pdf:nnn { catalog       } { extension } { 23 }
+\@@_tex_primitive_pdf:nnn { names         } { extension } { 24 }
+\@@_tex_primitive_pdf:nnn { fontattr      } { extension } { 25 }
+\@@_tex_primitive_pdf:nnn { includechars  } { extension } { 26 }
+\@@_tex_primitive_pdf:nnn { mapfile       } { extension } { 27 }
+\@@_tex_primitive_pdf:nnn { mapline       } { extension } { 28 }
+\@@_tex_primitive_pdf:nnn { trailer       } { extension } { 29 }
+\@@_tex_primitive_pdf:nnn { resettimer    } { extension } { 30 }
+\@@_tex_primitive_pdf:nnn { fontexpand    } { extension } { 31 }
+\@@_tex_primitive_pdf:nnn { setrandomseed } { extension } { 32 }
+\@@_tex_primitive_pdf:nnn { snaprefpoint  } { extension } { 33 }
+\@@_tex_primitive_pdf:nnn { snapy         } { extension } { 34 }
+\@@_tex_primitive_pdf:nnn { snapycomp     } { extension } { 35 }
+\@@_tex_primitive_pdf:nnn { glyphtounicode} { extension } { 36 }
+\@@_tex_primitive_pdf:nnn { colorstack    } { extension } { 37 }
+\@@_tex_primitive_pdf:nnn { setmatrix     } { extension } { 38 }
+\@@_tex_primitive_pdf:nnn { save          } { extension } { 39 }
+\@@_tex_primitive_pdf:nnn { restore       } { extension } { 40 }
+\@@_tex_primitive_pdf:nnn { nobuiltintounicode } { extension } { 41 }
 \@@_tex_primitive:nnn { openin                } { in_stream } { 1 }
 \@@_tex_primitive:nnn { closein               } { in_stream } { 0 }
 \@@_tex_primitive:nnn { begingroup            } { begin_group } { 0 }
@@ -1944,20 +2051,20 @@
 \@@_tex_primitive:nnn { lastnodetype          } { last_item } { 3 }
 \@@_tex_primitive:nnn { inputlineno           } { last_item } { 4 }
 \@@_tex_primitive:nnn { badness               } { last_item } { 5 }
-\@@_tex_primitive:nnn { pdftexversion         } { last_item } { 6 }
-\@@_tex_primitive:nnn { pdflastobj            } { last_item } { 7 }
-\@@_tex_primitive:nnn { pdflastxform          } { last_item } { 8 }
-\@@_tex_primitive:nnn { pdflastximage         } { last_item } { 9 }
-\@@_tex_primitive:nnn { pdflastximagepages    } { last_item } { 10 }
-\@@_tex_primitive:nnn { pdflastannot          } { last_item } { 11 }
-\@@_tex_primitive:nnn { pdflastxpos           } { last_item } { 12 }
-\@@_tex_primitive:nnn { pdflastypos           } { last_item } { 13 }
-\@@_tex_primitive:nnn { pdfretval             } { last_item } { 14 }
-\@@_tex_primitive:nnn { pdflastximagecolordepth } { last_item } { 15 }
-\@@_tex_primitive:nnn { pdfelapsedtime        } { last_item } { 16 }
-\@@_tex_primitive:nnn { pdfshellescape        } { last_item } { 17 }
-\@@_tex_primitive:nnn { pdfrandomseed         } { last_item } { 18 }
-\@@_tex_primitive:nnn { pdflastlink           } { last_item } { 19 }
+\@@_tex_primitive_pdf:nnn { texversion        } { last_item } { 6 }
+\@@_tex_primitive_pdf:nnn { lastobj           } { last_item } { 7 }
+\@@_tex_primitive_pdf:nnn { lastxform         } { last_item } { 8 }
+\@@_tex_primitive_pdf:nnn { lastximage        } { last_item } { 9 }
+\@@_tex_primitive_pdf:nnn { lastximagepages   } { last_item } { 10 }
+\@@_tex_primitive_pdf:nnn { lastannot         } { last_item } { 11 }
+\@@_tex_primitive_pdf:nnn { lastxpos          } { last_item } { 12 }
+\@@_tex_primitive_pdf:nnn { lastypos          } { last_item } { 13 }
+\@@_tex_primitive_pdf:nnn { retval            } { last_item } { 14 }
+\@@_tex_primitive_pdf:nnn { lastximagecolordepth } { last_item } { 15 }
+\@@_tex_primitive_pdf:nnn { elapsedtime       } { last_item } { 16 }
+\@@_tex_primitive_pdf:nnn { shellescape       } { last_item } { 17 }
+\@@_tex_primitive_pdf:nnn { randomseed        } { last_item } { 18 }
+\@@_tex_primitive_pdf:nnn { lastlink          } { last_item } { 19 }
 \@@_tex_primitive:nnn { eTeXversion           } { last_item } { 20 }
 \@@_tex_primitive:nnn { currentgrouplevel     } { last_item } { 21 }
 \@@_tex_primitive:nnn { currentgrouptype      } { last_item } { 22 }
@@ -1991,10 +2098,10 @@
 \@@_tex_primitive:nnn { everyjob              } { assign_toks } { 7 }
 \@@_tex_primitive:nnn { everycr               } { assign_toks } { 8 }
 \@@_tex_primitive:nnn { errhelp               } { assign_toks } { 9 }
-\@@_tex_primitive:nnn { pdfpagesattr          } { assign_toks } { 10 }
-\@@_tex_primitive:nnn { pdfpageattr           } { assign_toks } { 11 }
-\@@_tex_primitive:nnn { pdfpageresources      } { assign_toks } { 12 }
-\@@_tex_primitive:nnn { pdfpkmode             } { assign_toks } { 13 }
+\@@_tex_primitive_pdf:nnn { pagesattr         } { assign_toks } { 10 }
+\@@_tex_primitive_pdf:nnn { pageattr          } { assign_toks } { 11 }
+\@@_tex_primitive_pdf:nnn { pageresources     } { assign_toks } { 12 }
+\@@_tex_primitive_pdf:nnn { pkmode            } { assign_toks } { 13 }
 \@@_tex_primitive:nnn { everyeof              } { assign_toks } { 14 }
 \@@_tex_primitive:nnn { pretolerance          } { assign_int } { 0 }
 \@@_tex_primitive:nnn { tolerance             } { assign_int } { 1 }
@@ -2052,38 +2159,38 @@
 \@@_tex_primitive:nnn { holdinginserts        } { assign_int } { 53 }
 \@@_tex_primitive:nnn { errorcontextlines     } { assign_int } { 54 }
 \@@_tex_primitive:nnn { pdfoutput             } { assign_int } { 55 }
-\@@_tex_primitive:nnn { pdfcompresslevel      } { assign_int } { 56 }
-\@@_tex_primitive:nnn { pdfdecimaldigits      } { assign_int } { 57 }
-\@@_tex_primitive:nnn { pdfmovechars          } { assign_int } { 58 }
-\@@_tex_primitive:nnn { pdfimageresolution    } { assign_int } { 59 }
-\@@_tex_primitive:nnn { pdfpkresolution       } { assign_int } { 60 }
-\@@_tex_primitive:nnn { pdfuniqueresname      } { assign_int } { 61 }
-\@@_tex_primitive:nnn
-  { pdfoptionalwaysusepdfpagebox    } { assign_int } { 62 }
-\@@_tex_primitive:nnn
-  { pdfoptionpdfinclusionerrorlevel } { assign_int } { 63 }
-\@@_tex_primitive:nnn
-  { pdfoptionpdfminorversion        } { assign_int } { 64 }
-\@@_tex_primitive:nnn { pdfminorversion       } { assign_int } { 64 }
-\@@_tex_primitive:nnn { pdfforcepagebox       } { assign_int } { 65 }
-\@@_tex_primitive:nnn { pdfpagebox            } { assign_int } { 66 }
-\@@_tex_primitive:nnn
-  { pdfinclusionerrorlevel } { assign_int } { 67 }
-\@@_tex_primitive:nnn { pdfgamma              } { assign_int } { 68 }
-\@@_tex_primitive:nnn { pdfimagegamma         } { assign_int } { 69 }
-\@@_tex_primitive:nnn { pdfimagehicolor       } { assign_int } { 70 }
-\@@_tex_primitive:nnn { pdfimageapplygamma    } { assign_int } { 71 }
-\@@_tex_primitive:nnn { pdfadjustspacing      } { assign_int } { 72 }
-\@@_tex_primitive:nnn { pdfprotrudechars      } { assign_int } { 73 }
-\@@_tex_primitive:nnn { pdftracingfonts       } { assign_int } { 74 }
-\@@_tex_primitive:nnn { pdfobjcompresslevel   } { assign_int } { 75 }
-\@@_tex_primitive:nnn
-  { pdfadjustinterwordglue } { assign_int } { 76 }
-\@@_tex_primitive:nnn { pdfprependkern        } { assign_int } { 77 }
-\@@_tex_primitive:nnn { pdfappendkern         } { assign_int } { 78 }
-\@@_tex_primitive:nnn { pdfgentounicode       } { assign_int } { 79 }
-\@@_tex_primitive:nnn { pdfdraftmode          } { assign_int } { 80 }
-\@@_tex_primitive:nnn { pdfinclusioncopyfonts } { assign_int } { 81 }
+\@@_tex_primitive_pdf:nnn { compresslevel     } { assign_int } { 56 }
+\@@_tex_primitive_pdf:nnn { decimaldigits     } { assign_int } { 57 }
+\@@_tex_primitive_pdf:nnn { movechars         } { assign_int } { 58 }
+\@@_tex_primitive_pdf:nnn { imageresolution   } { assign_int } { 59 }
+\@@_tex_primitive_pdf:nnn { pkresolution      } { assign_int } { 60 }
+\@@_tex_primitive_pdf:nnn { uniqueresname     } { assign_int } { 61 }
+\@@_tex_primitive_pdf:nnn
+  { optionalwaysusepdfpagebox    } { assign_int } { 62 }
+\@@_tex_primitive_pdf:nnn
+  { optionpdfinclusionerrorlevel } { assign_int } { 63 }
+\@@_tex_primitive_pdf:nnn
+  { optionpdfminorversion        } { assign_int } { 64 }
+\@@_tex_primitive_pdf:nnn { minorversion      } { assign_int } { 64 }
+\@@_tex_primitive_pdf:nnn { forcepagebox      } { assign_int } { 65 }
+\@@_tex_primitive_pdf:nnn { pagebox           } { assign_int } { 66 }
+\@@_tex_primitive_pdf:nnn
+  { inclusionerrorlevel } { assign_int } { 67 }
+\@@_tex_primitive_pdf:nnn { gamma             } { assign_int } { 68 }
+\@@_tex_primitive_pdf:nnn { imagegamma        } { assign_int } { 69 }
+\@@_tex_primitive_pdf:nnn { imagehicolor      } { assign_int } { 70 }
+\@@_tex_primitive_pdf:nnn { imageapplygamma   } { assign_int } { 71 }
+\@@_tex_primitive_pdf:nnn { adjustspacing     } { assign_int } { 72 }
+\@@_tex_primitive_pdf:nnn { protrudechars     } { assign_int } { 73 }
+\@@_tex_primitive_pdf:nnn { tracingfonts      } { assign_int } { 74 }
+\@@_tex_primitive_pdf:nnn { objcompresslevel  } { assign_int } { 75 }
+\@@_tex_primitive_pdf:nnn
+  { adjustinterwordglue } { assign_int } { 76 }
+\@@_tex_primitive_pdf:nnn { prependkern       } { assign_int } { 77 }
+\@@_tex_primitive_pdf:nnn { appendkern        } { assign_int } { 78 }
+\@@_tex_primitive_pdf:nnn { gentounicode      } { assign_int } { 79 }
+\@@_tex_primitive_pdf:nnn { draftmode         } { assign_int } { 80 }
+\@@_tex_primitive_pdf:nnn { inclusioncopyfonts } { assign_int } { 81 }
 \@@_tex_primitive:nnn { tracingassigns        } { assign_int } { 82 }
 \@@_tex_primitive:nnn { tracinggroups         } { assign_int } { 83 }
 \@@_tex_primitive:nnn { tracingifs            } { assign_int } { 84 }
@@ -2115,19 +2222,19 @@
 \@@_tex_primitive:nnn { hoffset              } { assign_dimen } { 18 }
 \@@_tex_primitive:nnn { voffset              } { assign_dimen } { 19 }
 \@@_tex_primitive:nnn { emergencystretch     } { assign_dimen } { 20 }
-\@@_tex_primitive:nnn { pdfhorigin           } { assign_dimen } { 21 }
-\@@_tex_primitive:nnn { pdfvorigin           } { assign_dimen } { 22 }
-\@@_tex_primitive:nnn { pdfpagewidth         } { assign_dimen } { 23 }
-\@@_tex_primitive:nnn { pdfpageheight        } { assign_dimen } { 24 }
-\@@_tex_primitive:nnn { pdflinkmargin        } { assign_dimen } { 25 }
-\@@_tex_primitive:nnn { pdfdestmargin        } { assign_dimen } { 26 }
-\@@_tex_primitive:nnn { pdfthreadmargin      } { assign_dimen } { 27 }
-\@@_tex_primitive:nnn { pdffirstlineheight   } { assign_dimen } { 28 }
-\@@_tex_primitive:nnn { pdflastlinedepth     } { assign_dimen } { 29 }
-\@@_tex_primitive:nnn { pdfeachlineheight    } { assign_dimen } { 30 }
-\@@_tex_primitive:nnn { pdfeachlinedepth     } { assign_dimen } { 31 }
-\@@_tex_primitive:nnn { pdfignoreddimen      } { assign_dimen } { 32 }
-\@@_tex_primitive:nnn { pdfpxdimen           } { assign_dimen } { 33 }
+\@@_tex_primitive_pdf:nnn { horigin          } { assign_dimen } { 21 }
+\@@_tex_primitive_pdf:nnn { vorigin          } { assign_dimen } { 22 }
+\@@_tex_primitive_pdf:nnn { pagewidth        } { assign_dimen } { 23 }
+\@@_tex_primitive_pdf:nnn { pageheight       } { assign_dimen } { 24 }
+\@@_tex_primitive_pdf:nnn { linkmargin       } { assign_dimen } { 25 }
+\@@_tex_primitive_pdf:nnn { destmargin       } { assign_dimen } { 26 }
+\@@_tex_primitive_pdf:nnn { threadmargin     } { assign_dimen } { 27 }
+\@@_tex_primitive_pdf:nnn { firstlineheight  } { assign_dimen } { 28 }
+\@@_tex_primitive_pdf:nnn { lastlinedepth    } { assign_dimen } { 29 }
+\@@_tex_primitive_pdf:nnn { eachlineheight   } { assign_dimen } { 30 }
+\@@_tex_primitive_pdf:nnn { eachlinedepth    } { assign_dimen } { 31 }
+\@@_tex_primitive_pdf:nnn { ignoreddimen     } { assign_dimen } { 32 }
+\@@_tex_primitive_pdf:nnn { pxdimen          } { assign_dimen } { 33 }
 \@@_tex_primitive:nnn { lineskip              } { assign_glue } { 0 }
 \@@_tex_primitive:nnn { baselineskip          } { assign_glue } { 1 }
 \@@_tex_primitive:nnn { parskip               } { assign_glue } { 2 }
@@ -2153,7 +2260,7 @@
 \@@_tex_primitive:nnn { rpcode           } { assign_font_int } { 3 }
 \@@_tex_primitive:nnn { efcode           } { assign_font_int } { 4 }
 \@@_tex_primitive:nnn { tagcode          } { assign_font_int } { 5 }
-\@@_tex_primitive:nnn { pdfnoligatures   } { assign_font_int } { 6 }
+\@@_tex_primitive_pdf:nnn { noligatures  } { assign_font_int } { 6 }
 \@@_tex_primitive:nnn { knbscode         } { assign_font_int } { 7 }
 \@@_tex_primitive:nnn { stbscode         } { assign_font_int } { 8 }
 \@@_tex_primitive:nnn { shbscode         } { assign_font_int } { 9 }
@@ -2226,12 +2333,12 @@
 \@@_tex_primitive:nnn { scrollmode      } { set_interaction } { 2 }
 \@@_tex_primitive:nnn { errorstopmode   } { set_interaction } { 3 }
 \@@_tex_primitive:nnn { letterspacefont } { letterspace_font } { 0 }
-\@@_tex_primitive:nnn { pdfcopyfont     } { pdf_copy_font } { 0 }
+\@@_tex_primitive_pdf:nnn { copyfont    } { pdf_copy_font } { 0 }
 \@@_tex_primitive:nnn { undefined         } { undefined_cs } { 0 }
 \@@_tex_primitive:nnn { ndefined          } { undefined_cs } { 0 }
 \@@_tex_primitive:nnn { expandafter       } { expand_after } { 0 }
 \@@_tex_primitive:nnn { unless            } { expand_after } { 1 }
-\@@_tex_primitive:nnn { pdfprimitive      } { no_expand } { 1 }
+\@@_tex_primitive_pdf:nnn { primitive     } { no_expand } { 1 }
 \@@_tex_primitive:nnn { noexpand          } { no_expand } { 0 }
 \@@_tex_primitive:nnn { input             } { input } { 0 }
 \@@_tex_primitive:nnn { endinput          } { input } { 1 }
@@ -2242,12 +2349,12 @@
 \@@_tex_primitive:nnn { ifdim             } { if_test } { 3 }
 \@@_tex_primitive:nnn { ifodd             } { if_test } { 4 }
 \@@_tex_primitive:nnn { ifvmode           } { if_test } { 5 }
-\@@_tex_primitive:nnn { ifhmode           } { if_test } { 6 }
-\@@_tex_primitive:nnn { ifmmode           } { if_test } { 7 }
-\@@_tex_primitive:nnn { ifinner           } { if_test } { 8 }
+\@@_tex_primitive:nnn { ifhmode           } { if_test } { 5 }
+\@@_tex_primitive:nnn { ifmmode           } { if_test } { 5 }
+\@@_tex_primitive:nnn { ifinner           } { if_test } { 5 }
 \@@_tex_primitive:nnn { ifvoid            } { if_test } { 9 }
-\@@_tex_primitive:nnn { ifhbox            } { if_test } { 10 }
-\@@_tex_primitive:nnn { ifvbox            } { if_test } { 11 }
+\@@_tex_primitive:nnn { ifhbox            } { if_test } { 9 }
+\@@_tex_primitive:nnn { ifvbox            } { if_test } { 9 }
 \@@_tex_primitive:nnn { ifx               } { if_test } { 12 }
 \@@_tex_primitive:nnn { ifeof             } { if_test } { 13 }
 \@@_tex_primitive:nnn { iftrue            } { if_test } { 14 }
@@ -2257,13 +2364,30 @@
 \@@_tex_primitive:nnn { ifcsname          } { if_test } { 18 }
 \@@_tex_primitive:nnn { iffontchar        } { if_test } { 19 }
 \@@_tex_primitive:nnn { ifincsname        } { if_test } { 20 }
+\@@_tex_primitive:nnn { ifprimitive       } { if_test } { 21 }
 \@@_tex_primitive:nnn { ifpdfprimitive    } { if_test } { 21 }
+\@@_tex_primitive:nnn { ifabsnum          } { if_test } { 22 }
 \@@_tex_primitive:nnn { ifpdfabsnum       } { if_test } { 22 }
+\@@_tex_primitive:nnn { ifabsdim          } { if_test } { 23 }
 \@@_tex_primitive:nnn { ifpdfabsdim       } { if_test } { 23 }
+\bool_if:nT { \sys_if_engine_ptex_p: || \sys_if_engine_uptex_p: }
+  {
+    \@@_tex_primitive:nnn { iftdir        } { if_test } { 5 }
+    \@@_tex_primitive:nnn { ifydir        } { if_test } { 5 }
+    \@@_tex_primitive:nnn { ifddir        } { if_test } { 5 }
+    \@@_tex_primitive:nnn { ifmdir        } { if_test } { 5 }
+    \@@_tex_primitive:nnn { iftbox        } { if_test } { 9 }
+    \@@_tex_primitive:nnn { ifybox        } { if_test } { 9 }
+    \@@_tex_primitive:nnn { ifdbox        } { if_test } { 9 }
+    \@@_tex_primitive:nnn { ifmbox        } { if_test } { 9 }
+    \@@_tex_primitive:nnn { ifjfont       } { if_test } { 24 }
+    \@@_tex_primitive:nnn { iftfont       } { if_test } { 24 }
+  }
 \@@_tex_primitive:nnn { fi                } { fi_or_else } { 2 }
 \@@_tex_primitive:nnn { else              } { fi_or_else } { 3 }
 \@@_tex_primitive:nnn { or                } { fi_or_else } { 4 }
 \@@_tex_primitive:nnn { csname            } { cs_name } { 0 }
+\@@_tex_primitive:nnn { lastnamedcs       } { cs_name } { 1 }
 \@@_tex_primitive:nnn { number            } { convert } { 0 }
 \@@_tex_primitive:nnn { romannumeral      } { convert } { 1 }
 \@@_tex_primitive:nnn { string            } { convert } { 2 }
@@ -2270,33 +2394,32 @@
 \@@_tex_primitive:nnn { meaning           } { convert } { 3 }
 \@@_tex_primitive:nnn { fontname          } { convert } { 4 }
 \@@_tex_primitive:nnn { eTeXrevision      } { convert } { 5 }
-\@@_tex_primitive:nnn { pdftexrevision    } { convert } { 6 }
-\@@_tex_primitive:nnn { pdftexbanner      } { convert } { 7 }
+\@@_tex_primitive_pdf:nnn { texrevision   } { convert } { 6 }
+\@@_tex_primitive_pdf:nnn { texbanner     } { convert } { 7 }
 \@@_tex_primitive:nnn { pdffontname       } { convert } { 8 }
-\@@_tex_primitive:nnn { pdffontobjnum     } { convert } { 9 }
-\@@_tex_primitive:nnn { pdffontsize       } { convert } { 10 }
-\@@_tex_primitive:nnn { pdfpageref        } { convert } { 11 }
-\@@_tex_primitive:nnn { pdfxformname      } { convert } { 12 }
-\@@_tex_primitive:nnn { pdfescapestring   } { convert } { 13 }
-\@@_tex_primitive:nnn { pdfescapename     } { convert } { 14 }
+\@@_tex_primitive_pdf:nnn { fontobjnum    } { convert } { 9 }
+\@@_tex_primitive_pdf:nnn { fontsize      } { convert } { 10 }
+\@@_tex_primitive_pdf:nnn { pageref       } { convert } { 11 }
+\@@_tex_primitive_pdf:nnn { xformname     } { convert } { 12 }
+\@@_tex_primitive_pdf:nnn { escapestring  } { convert } { 13 }
+\@@_tex_primitive_pdf:nnn { escapename    } { convert } { 14 }
 \@@_tex_primitive:nnn { leftmarginkern    } { convert } { 15 }
 \@@_tex_primitive:nnn { rightmarginkern   } { convert } { 16 }
-\@@_tex_primitive:nnn
-  { \sys_if_engine_xetex:F { pdf } strcmp } { convert } { 17 }
-\@@_tex_primitive:nnn { pdfcolorstackinit } { convert } { 18 }
-\@@_tex_primitive:nnn { pdfescapehex      } { convert } { 19 }
-\@@_tex_primitive:nnn { pdfunescapehex    } { convert } { 20 }
-\@@_tex_primitive:nnn { pdfcreationdate   } { convert } { 21 }
-\@@_tex_primitive:nnn { pdffilemoddate    } { convert } { 22 }
-\@@_tex_primitive:nnn { pdffilesize       } { convert } { 23 }
-\@@_tex_primitive:nnn { pdfmdfivesum      } { convert } { 24 }
-\@@_tex_primitive:nnn { pdffiledump       } { convert } { 25 }
-\@@_tex_primitive:nnn { pdfmatch          } { convert } { 26 }
-\@@_tex_primitive:nnn { pdflastmatch      } { convert } { 27 }
-\@@_tex_primitive:nnn { pdfuniformdeviate } { convert } { 28 }
-\@@_tex_primitive:nnn { pdfnormaldeviate  } { convert } { 29 }
-\@@_tex_primitive:nnn { pdfinsertht       } { convert } { 30 }
-\@@_tex_primitive:nnn { pdfximagebbox     } { convert } { 31 }
+\@@_tex_primitive_pdf:nnn { strcmp        } { convert } { 17 }
+\@@_tex_primitive_pdf:nnn { colorstackinit } { convert } { 18 }
+\@@_tex_primitive_pdf:nnn { escapehex     } { convert } { 19 }
+\@@_tex_primitive_pdf:nnn { unescapehex   } { convert } { 20 }
+\@@_tex_primitive_pdf:nnn { creationdate  } { convert } { 21 }
+\@@_tex_primitive_pdf:nnn { filemoddate   } { convert } { 22 }
+\@@_tex_primitive_pdf:nnn { filesize      } { convert } { 23 }
+\@@_tex_primitive_pdf:nnn { mdfivesum     } { convert } { 24 }
+\@@_tex_primitive_pdf:nnn { filedump      } { convert } { 25 }
+\@@_tex_primitive_pdf:nnn { match         } { convert } { 26 }
+\@@_tex_primitive_pdf:nnn { lastmatch     } { convert } { 27 }
+\@@_tex_primitive_pdf:nnn { uniformdeviate } { convert } { 28 }
+\@@_tex_primitive_pdf:nnn { normaldeviate } { convert } { 29 }
+\@@_tex_primitive_pdf:nnn { insertht      } { convert } { 30 }
+\@@_tex_primitive_pdf:nnn { ximagebbox    } { convert } { 31 }
 \@@_tex_primitive:nnn { jobname           } { convert } { 32 }
 \sys_if_engine_luatex:T
   { \@@_tex_primitive:nnn { directlua     } { convert } { 33 } }
@@ -2581,13 +2704,30 @@
 %   Complain about an unknown primitive, and consider it as if it were
 %   \tn{relax}.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_set_cmd_aux_unknown:
+\sys_if_engine_luatex:TF
   {
-    \exp_last_unbraced:NV \@@_set_cmd_aux_primitive:nn
-      \c_@@_tex_relax_tl
-    \@@_error:nxxxx { unknown-primitive }
-      { \l_@@_head_meaning_tl } { } { } { }
+    \cs_new_protected:Npn \@@_set_cmd_aux_unknown:
+      {
+        \exp_last_unbraced:NV \@@_set_cmd_aux_primitive:nn
+          \c_@@_tex_relax_tl
+        \@@_tl_if_in:ooTF \l_@@_head_meaning_tl
+          { \tl_to_str:n { xpandable~luacall } }
+          { }
+          {
+            \@@_error:nxxxx { unknown-primitive }
+              { \l_@@_head_meaning_tl } { } { } { }
+          }
+      }
   }
+  {
+    \cs_new_protected:Npn \@@_set_cmd_aux_unknown:
+      {
+        \exp_last_unbraced:NV \@@_set_cmd_aux_primitive:nn
+          \c_@@_tex_relax_tl
+        \@@_error:nxxxx { unknown-primitive }
+          { \l_@@_head_meaning_tl } { } { } { }
+      }
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -3225,8 +3365,7 @@
           { \@@_error:nxxxx { internal } { expandable } { } { } { } }
       }
       {
-        \@@_error:nxxxx { unknown-primitive }
-          { \l_@@_head_meaning_tl } { } { } { }
+        \@@_set_cmd_aux_unknown:
         \@@_input_gpop_tl:N \l_@@_tmpa_tl
         \tl_put_right:NV \l_@@_head_tl \l_@@_tmpa_tl
         \exp_args:NV \@@_back_input:o \l_@@_head_tl
@@ -3341,7 +3480,7 @@
 % \begin{macro}{\@@_scan_optional_equals:}
 %   See \TeX{}'s |scan_optional_equals|.  In all cases we forcefully
 %   insert an equal sign in the output, because this sign is required,
-%   as \cs{@@_scan_something_internal:n} leaves raw numbers in
+%   as \cs{@@_rescan_something_internal:n} leaves raw numbers in
 %   the previous-input sequence.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_optional_equals:
@@ -3557,8 +3696,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% ^^A todo: rename this function because all other scan functions do get_x_next themselves.
-% \begin{macro}{\@@_scan_something_internal:n}
+% \begin{macro}{\@@_rescan_something_internal:n}
 % \begin{macro}{\@@_scan_something_aux:nwn}
 %   Receives an (explicit) \enquote{level} argument:
 %   \begin{itemize}
@@ -3602,7 +3740,7 @@
 %   |\parindent=\parskip| where a skip or a dimen is downgraded to a
 %   dimen or an int, or when there was an error).
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_scan_something_internal:n #1
+\cs_new_protected:Npn \@@_rescan_something_internal:n #1
   {
     \@@_set_cmd:
     \@@_set_action_text:
@@ -3617,13 +3755,13 @@
         \@@_back_input:
         \@@_tex_error:nV { missing-number } \l_@@_head_tl
         \@@_thing_use_get:nnNN { 1 } {#3} \c_zero_dim \l_@@_tmpa_tl
-        \@@_scan_something_internal_auxii:Vn \l_@@_tmpa_tl { 1 }
+        \@@_rescan_something_internal_auxii:Vn \l_@@_tmpa_tl { 1 }
         \@@_break:w
       }
     \int_compare:nNnT {#1} = { 8 }
       {
         \@@_tex_error:nV { the-cannot } \l_@@_head_tl
-        \@@_scan_something_internal_auxii:nn 0 { 0 }
+        \@@_rescan_something_internal_auxii:nn 0 { 0 }
         \@@_break:w
       }
     \tl_if_empty:nF {#2}
@@ -3636,11 +3774,11 @@
     \int_compare:nNnTF {#3} < { 4 }
       { \@@_thing_use_get:nnNN {#1} {#3} \l_@@_head_tl \l_@@_tmpa_tl }
       { \tl_set:Nx \l_@@_tmpa_tl { \@@_the:w \l_@@_head_tl } }
-    \@@_scan_something_internal_auxii:Vn \l_@@_tmpa_tl {#1}
+    \@@_rescan_something_internal_auxii:Vn \l_@@_tmpa_tl {#1}
     \@@_break_point:
     \int_compare:nNnT {#3} < { 4 } { \@@_print_action: }
   }
-\cs_new_protected:Npn \@@_scan_something_internal_auxii:nn #1#2
+\cs_new_protected:Npn \@@_rescan_something_internal_auxii:nn #1#2
   {
     \@@_prev_input_silent:n {#1}
     \@@_set_action_text:
@@ -3648,12 +3786,11 @@
       { \g_@@_action_text_str \use:n { ~ => ~ } \tl_to_str:n {#1} }
     \int_gset:Nn \g_@@_val_level_int {#2}
   }
-\cs_generate_variant:Nn \@@_scan_something_internal_auxii:nn { V }
+\cs_generate_variant:Nn \@@_rescan_something_internal_auxii:nn { V }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
 %
-% ^^A todo: \the can be followed by ignore_spaces
 % \begin{macro}[EXP]
 %   {\@@_thing_case:, \@@_thing_last_item:, \@@_thing_register:}
 %   This expands to a digit (the level generated by whatever token is
@@ -3662,7 +3799,7 @@
 %   |cmd| integer, but for |last_item|, |set_aux| and |register|, the level of the
 %   token depends on the |char| integer.  When the token is not allowed
 %   after \tn{the} (or at any other position where
-%   \cs{@@_scan_something_internal:n} is called), the resulting level
+%   \cs{@@_rescan_something_internal:n} is called), the resulting level
 %   is~$8$, large enough so that the main function knows it is
 %   forbidden.
 %    \begin{macrocode}
@@ -3907,7 +4044,7 @@
     \@@_scan_signs:
     \@@_set_cmd:
     \@@_cmd_if_internal:TF
-      { \@@_scan_something_internal:n { 0 } }
+      { \@@_rescan_something_internal:n { 0 } }
       { \@@_scan_int_char: }
   }
 \cs_new_protected:Npn \@@_scan_int_char:
@@ -4001,8 +4138,8 @@
     \@@_cmd_if_internal:TF
       {
         \int_compare:nNnTF {#1} = { 3 }
-          { \@@_scan_something_internal:n { 3 } }
-          { \@@_scan_something_internal:n { 1 } }
+          { \@@_rescan_something_internal:n { 3 } }
+          { \@@_rescan_something_internal:n { 1 } }
         \int_compare:nNnT \g_@@_val_level_int = { 0 }
           { \@@_scan_dim_unit:nN {#1} #2 }
       }
@@ -4055,7 +4192,7 @@
     \@@_cmd_if_internal:TF
       {
         \@@_prev_input_gpush:
-        \@@_scan_something_internal:n {#1}
+        \@@_rescan_something_internal:n {#1}
         \int_compare:nNnTF \g_@@_val_level_int = { 0 }
           { \@@_prev_input_join_get:nnN {#1} { sp } \l_@@_tmpa_tl }
           { \@@_prev_input_join_get:nnN {#1} { } \l_@@_tmpa_tl }
@@ -4132,7 +4269,7 @@
     \@@_set_cmd:
     \@@_cmd_if_internal:TF
       {
-        \@@_scan_something_internal:n {#1}
+        \@@_rescan_something_internal:n {#1}
         \int_case:nnF \g_@@_val_level_int
           {
             { 0 } { \@@_scan_dim_unit:nN {#1} \c_false_bool }
@@ -4155,17 +4292,22 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% ^^A todo: allow \input".. .."
 % \begin{macro}{\@@_scan_file_name:}
-% ^^A todo: area_delimiter and ext_delimiter ??
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_file_name:
   {
-    \bool_gset_true:N \g_@@_name_in_progress_bool
-    \@@_get_x_non_blank:
-    \@@_scan_file_name_loop:
-    \bool_gset_false:N \g_@@_name_in_progress_bool
-    \@@_prev_input_silent:n { ~ }
+    \@@_get_x_non_relax:
+    \token_if_eq_catcode:NNTF \l_@@_head_token \c_group_begin_token
+      { \@@_scan_group_x:N \c_false_bool }
+      {
+        \@@_back_input:
+        \bool_gset_true:N \g_@@_name_in_progress_bool
+        \bool_gset_false:N \g_@@_quotes_bool
+        \@@_get_x_non_blank:
+        \@@_scan_file_name_loop:
+        \bool_gset_false:N \g_@@_name_in_progress_bool
+        \@@_prev_input_silent:n { ~ }
+      }
   }
 \cs_new_protected:Npn \@@_scan_file_name_loop:
   {
@@ -4174,8 +4316,14 @@
       {
         \tl_set:Nx \l_@@_tmpa_tl
           { \@@_token_to_char:N \l_@@_head_token }
-        \tl_if_eq:NNF \l_@@_tmpa_tl \c_space_tl
+        \tl_if_eq:NNT \l_@@_tmpa_tl \c_@@_dq_tl
           {
+            \bool_if:NTF \g_@@_quotes_bool
+              { \bool_set_false:N } { \bool_set_true:N } \g_@@_quotes_bool
+          }
+        \bool_if:NTF \g_@@_quotes_bool
+          { \use:n } { \tl_if_eq:NNF \l_@@_tmpa_tl \c_space_tl }
+          {
             \@@_prev_input_silent:V \l_@@_tmpa_tl
             \@@_get_x_next:
             \@@_scan_file_name_loop:
@@ -4182,6 +4330,7 @@
           }
       }
   }
+\bool_new:N \g_@@_quotes_bool
 %    \end{macrocode}
 % \end{macro}
 %
@@ -4233,7 +4382,6 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% ^^A todo: provide separate functions for defs (avoid hash doubling).
 % \begin{macro}{\@@_scan_toks:NN}
 %   The boolean |#1| is true if we are making a definition (then we
 %   start by scanning the parameter text), false if we are simply
@@ -4579,7 +4727,6 @@
     \token_if_eq_meaning:NNTF \l_@@_head_token \@@_hbox:w
       { \@@_box_hook:N \tex_everyhbox:D }
       { \@@_box_hook:N \tex_everyvbox:D }
-      % ^^A todo: TeX calls |normal_paragraph| here.
     \@@_scan_spec:
     \@@_prev_input_gpop:N \l_@@_head_tl
     \@@_set_action_text:x
@@ -4671,13 +4818,18 @@
   {
     \tex_char:D #1 \scan_stop:
     \@@_charcode_if_safe:nTF {#1}
-      { \tl_set:Nx \l_@@_tmpa_tl { \char_generate:nn {#1} { 12 } } }
       {
+        \tl_set:Nx \l_@@_tmpa_tl { \char_generate:nn {#1} { 12 } }
+        \gtl_gput_right:NV \g_@@_output_gtl \l_@@_tmpa_tl
+        \@@_print_action:x { \tl_to_str:N \l_@@_tmpa_tl }
+      }
+      {
         \tl_set:Nx \l_@@_tmpa_tl
           { \exp_not:N \char \int_eval:n {#1} ~ }
+        \gtl_gput_right:NV \g_@@_output_gtl \l_@@_tmpa_tl
+        \@@_print_action:x
+          { " \char_generate:nn {#1} { 12 } " = \tl_to_str:N \l_@@_tmpa_tl }
       }
-    \gtl_gput_right:NV \g_@@_output_gtl \l_@@_tmpa_tl
-    \@@_print_action:x { \tl_to_str:N \l_@@_tmpa_tl }
   }
 \cs_generate_variant:Nn \@@_char:n { V }
 \cs_new_protected:Npn \@@_char:x
@@ -4690,11 +4842,13 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_char_in_mmode:n #1
   {
-    \int_compare:nNnTF { \tex_mathcode:D #1 } = { "8000 }
+    \int_compare:nNnTF { \tex_mathcode:D #1 }
+      = { \sys_if_engine_luatex:TF { "1000000 } { "8000 } }
       { % math active
-        \@@_exp_args:NNx \gtl_set:Nn \l_@@_head_gtl
-          { \char_generate:nn {#1} { 12 } }
+        \@@_active_do:nn {#1} { \gtl_set:Nn \l_@@_head_gtl }
         \@@_back_input:
+        \@@_print_action:x
+          { \char_generate:nn {#1} { 12 } ~ active }
       }
       { \@@_char:n {#1} }
   }
@@ -4711,7 +4865,7 @@
   {
     \tex_mathchar:D #1 \scan_stop:
     \tl_set:Nx \l_@@_tmpa_tl
-      { \exp_not:N \mathchar \int_eval:n {#1} ~ }
+      { \exp_not:N \mathchar " \int_to_hex:n {#1} ~ }
     \gtl_gput_right:NV \g_@@_output_gtl \l_@@_tmpa_tl
     \@@_print_action:x { \tl_to_str:N \l_@@_tmpa_tl }
   }
@@ -4743,17 +4897,18 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_end_graf:}
+% \begin{macro}{\@@_par_if_hmode:}
+%   This is like the |end_graf| procedure in \TeX{}.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_end_graf:
-  { \mode_if_horizontal:T { \@@_normal_paragraph: } }
+\cs_new_protected:Npn \@@_par_if_hmode:
+  { \mode_if_horizontal:T { \@@_par: } }
 %    \end{macrocode}
 % \end{macro}
 %
 % ^^A todo: Do we need to do more?
-% \begin{macro}{\@@_normal_paragraph:}
+% \begin{macro}{\@@_par:}
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_normal_paragraph:
+\cs_new_protected:Npn \@@_par:
   {
     \tex_par:D
     \gtl_gput_right:Nn \g_@@_output_gtl { \par }
@@ -4773,15 +4928,18 @@
 %
 % \subsection{Groups}
 %
-% ^^A todo: implement \@@_end_align_group:
-% ^^A todo: implement \@@_end_no_align_group: (start = \@@_end_graf:)
-% ^^A todo: implement \@@_end_output_group:
-% ^^A todo: implement \@@_end_disc_group:
-% ^^A todo: implement \@@_end_math_choice_group:
+% \begin{variable}{\l_@@_choice_int}
+%   Used by \tn{mathchoice} etc to keep
+%   track of which argument we are currently in.
+%    \begin{macrocode}
+\int_new:N \l_@@_choice_int
+%    \end{macrocode}
+% \end{variable}
 %
 % \begin{macro}{\@@_handle_right_brace:}
 %   When an end-group character is sensed, the result depends on the
-%   current group type.
+%   current group type.  Suppress the |after_group| tokens in
+%   \tn{discretionary} or \tn{mathchoice}.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_handle_right_brace:
   {
@@ -4789,22 +4947,27 @@
       {
         \gtl_gconcat:NNN \g_@@_output_gtl
           \g_@@_output_gtl \c_group_end_gtl
-        \@@_back_input_gtl:N \l_@@_after_group_gtl
+        \int_case:nnF \@@_currentgrouptype:
+          {
+            { 10 } { } % disc
+            { 13 } { } % math_choice
+          }
+          { \@@_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
+            { 4 } { \@@_par_if_hmode: \@@_end_box_group: } % vbox
+            { 5 } { \@@_par_if_hmode: \@@_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
+            { 10 } { \@@_end_choice_group:NN 2 \discretionary  } % disc
+            { 11 } { \@@_par_if_hmode: \@@_end_simple_group: } % insert
+            { 12 } { \@@_par_if_hmode: \@@_end_simple_group: } % vcenter
+            { 13 } { \@@_end_choice_group:NN 3 \mathchoice } % math_choice
           }
       }
       { % bottom_level, semi_simple, math_shift, math_left
@@ -4860,6 +5023,70 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_end_align_group:}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_end_align_group:
+  {
+    \@@_not_implemented:n { end_align_group }
+    \@@_end_simple_group:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_end_no_align_group:}
+%   ^^A todo: should start with \@@_par_if_hmode:
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_end_no_align_group:
+  {
+    \@@_not_implemented:n { end_no_align_group }
+    \@@_end_simple_group:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_end_output_group:}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_end_output_group:
+  {
+    \@@_not_implemented:n { end_output_group }
+    \@@_end_simple_group:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_end_choice_group:NN, \@@_end_choice_group:nN}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_end_choice_group:NN #1#2
+  {
+    \int_compare:nNnTF \l_@@_choice_int > {#1}
+      {
+        \@@_back_input_gtl:N \l_@@_after_group_gtl
+        \c_group_end_token
+        \@@_print_action:x
+          { \token_to_str:N #2 \prg_replicate:nn { #1 + 1 } { {...} } }
+      }
+      { \exp_args:NV \@@_end_choice_group:nN \l_@@_choice_int #2 }
+  }
+\cs_new_protected:Npn \@@_end_choice_group:nN #1#2
+  {
+    \@@_scan_left_brace:
+    \gtl_gconcat:NNN \g_@@_output_gtl
+      \g_@@_output_gtl \c_group_begin_gtl
+    \@@_back_input_gtl:N \l_@@_after_group_gtl
+    \use:n \c_group_end_token
+    \use:n \c_group_begin_token
+    \int_set:Nn \l_@@_choice_int { #1 + 1 }
+    \gtl_clear:N \l_@@_after_group_gtl
+    \@@_print_action:x
+      {
+        \token_to_str:N #2
+        \prg_replicate:nn {#1} { { ... } }
+        \iow_char:N \{
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\@@_off_save:}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_off_save:
@@ -4891,7 +5118,6 @@
 %
 % \subsection{Modes}
 % ^^A todo: implement \aftergroup and things happening at end-group
-% ^^A todo: implement \@@_scan_math:
 %
 % \begin{macro}
 %   {\@@_mode_math:n, \@@_mode_non_math:n, \@@_mode_vertical:n}
@@ -4938,7 +5164,6 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% ^^A todo: should push_math be provided?
 % \begin{macro}{\@@_goto_inner_math:}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_goto_inner_math:
@@ -4962,17 +5187,18 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_after_math:}
+%   In display math mode, or in a group started by \tn{eqno} or
+%   \tn{leqno} (namely in inner math mode with non-zero
+%   \cs{l_@@_choice_int}), search for another
+%   |$|; otherwise simply close the inner math.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_after_math:
   {
     \mode_if_inner:TF
+      { \int_compare:nNnTF \l_@@_choice_int > 0 }
+      { \use_i:nn }
       {
         \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
-        \@@_back_input_gtl:N \l_@@_after_group_gtl
-        $ % $
-      }
-      {
-        \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
         \@@_get_x_next:
         \token_if_eq_catcode:NNF
           \l_@@_head_token \c_math_toggle_token
@@ -4985,6 +5211,11 @@
         \@@_back_input_gtl:N \l_@@_after_group_gtl
         $ $
       }
+      {
+        \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+        \@@_back_input_gtl:N \l_@@_after_group_gtl
+        $ % $
+      }
     \@@_print_action:
   }
 %    \end{macrocode}
@@ -5109,8 +5340,6 @@
   { \l_@@_head_token \@@_print_action: }
 %    \end{macrocode}
 %
-% ^^A todo: wrong: needs to collect subsup before output (otherwise b{}^2{}_3)
-% ^^A todo: wrong: mathcode "8000 is not recognized.
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { superscript_char }                     % 7
   { \@@_mode_math:n { \@@_sub_sup: } }
@@ -5120,6 +5349,10 @@
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
+    \@@_do_one_atom:
+  }
+\cs_new_protected:Npn \@@_do_one_atom:
+  {
     \@@_get_x_non_relax:
     \@@_set_cmd:
     \int_case:nnTF \l_@@_head_cmd_int
@@ -5165,7 +5398,12 @@
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { endv }                                 % 9
-  { \@@_not_implemented:n { alignments } }
+  {
+    \@@_mode_non_math:n
+      {
+        \@@_not_implemented:n { alignments }
+      }
+  }
 %    \end{macrocode}
 %
 % Blank spaces are ignored in vertical and math modes in the same way as
@@ -5205,10 +5443,10 @@
     \@@_mode_non_math:n
       {
         \mode_if_vertical:TF
-          { \@@_normal_paragraph: }
+          { \@@_par: }
           {
             % if align_state<0 then off_save;
-            \@@_end_graf:
+            \@@_par_if_hmode:
             \mode_if_vertical:T
               { \mode_if_inner:F { \@@_build_page: } }
           }
@@ -5376,7 +5614,7 @@
         { 2 }
           { % showthe
             \@@_get_x_next:
-            \@@_scan_something_internal:n { 5 }
+            \@@_rescan_something_internal:n { 5 }
             \@@_prev_input_gpop:N \l_@@_head_tl
             \@@_exp_args:Nx \use:n
               { \tex_showtokens:D { \tl_tail:N \l_@@_head_tl } }
@@ -5560,14 +5798,14 @@
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
-    \@@_do_box:N \c_true_bool
+    \tl_if_head_eq_meaning:VNTF \l_@@_head_tl \tex_shipout:D
+      { \@@_do_box:N \c_false_bool }
+      { \@@_do_box:N \c_true_bool }
   }
 %    \end{macrocode}
 %
 % \subsubsection{From 32 to 47}
 %
-% ^^A todo: implement \@@_begin_insert_or_adjust:
-%
 % \begin{itemize}
 % \item |halign=32|
 % \item |valign=33|
@@ -5593,7 +5831,7 @@
 \@@_new_tex_cmd:nn { valign }                               % 33
   { \@@_not_implemented:n { valign } }
 \@@_new_tex_cmd:nn { no_align }                             % 34
-  { \@@_not_implemented:n { noalign } }
+  { \l_@@_head_token \@@_print_action: }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
@@ -5614,15 +5852,36 @@
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { insert }                               % 37
-  { \@@_begin_insert_or_adjust: }
+  {
+    \@@_prev_input_gpush:N \l_@@_head_tl
+    \@@_print_action:
+    \@@_scan_int:
+    \@@_begin_insert_or_adjust:
+  }
 \@@_new_tex_cmd:nn { vadjust }                              % 38
   {
     \mode_if_vertical:TF
-      { \@@_forbidden_case: } { \@@_begin_insert_or_adjust: }
+      { \@@_forbidden_case: }
+      {
+        \@@_prev_input_gpush:N \l_@@_head_tl
+        \@@_print_action:
+        \@@_scan_keyword:nTF { pPrReE }
+        \@@_begin_insert_or_adjust:
+      }
   }
+\cs_new_protected:Npn \@@_begin_insert_or_adjust:
+  {
+    \@@_scan_left_brace:
+    \@@_prev_input_gpop:N \l_@@_head_tl
+    \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+    \gtl_gconcat:NNN \g_@@_output_gtl
+      \g_@@_output_gtl \c_group_begin_gtl
+    \tl_use:N \l_@@_head_tl \c_group_begin_token
+    \@@_print_action:x
+      { \tl_to_str:N \l_@@_head_tl \iow_char:N \{ }
+  }
 %    \end{macrocode}
 %
-% ^^A todo: implement the internal \pdfprimitive business.
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { ignore_spaces }                        % 39
   {
@@ -5767,11 +6026,7 @@
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
     \@@_scan_int:
-    \@@_scan_math:
-    \@@_prev_input_gpop:N \l_@@_head_tl
-    \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
-    \tl_use:N \l_@@_head_tl \scan_stop:
-    \@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
+    \@@_do_one_atom:
   }
 %    \end{macrocode}
 % \end{macro}
@@ -5794,7 +6049,14 @@
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { discretionary }                        % 47
-  { \@@_not_implemented:n { discretionary } }
+  {
+    \@@_mode_non_vertical:n
+      {
+        \int_compare:nNnTF \l_@@_head_char_int = { 1 }
+          { \@@_output_head_token: }
+          { \@@_do_choice: }
+      }
+  }
 %    \end{macrocode}
 %
 % \subsubsection{Maths: from 48 to 56}
@@ -5813,47 +6075,144 @@
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { eq_no }                                % 48
-  { \@@_not_implemented:n { eqno } }
+  {
+    \mode_if_math:TF
+      {
+        \mode_if_inner:TF
+          { \@@_off_save: }
+          {
+            \int_compare:nNnTF \tex_currentgrouptype:D = { 15 }
+              {
+                \@@_box_hook:N \tex_everymath:D
+                \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+                \l_@@_head_token
+                \@@_box_hook_end:
+                \int_set:Nn \l_@@_choice_int { 1 }
+              }
+              { \@@_off_save: }
+          }
+      }
+      { \@@_forbidden_case: }
+  }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { left_right }                           % 49
-  { \@@_not_implemented:n { left/right } }
+  {
+    \@@_mode_math:n
+      {
+        \@@_prev_input_gpush:N \l_@@_head_tl
+        \@@_print_action:
+        \@@_scan_delimiter:
+        \@@_prev_input_gpop:N \l_@@_head_tl
+        \tl_if_head_eq_meaning:nNTF \l_@@_head_tl \tex_left:D
+          {
+            \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+            \tl_use:N \l_@@_head_tl \scan_stop:
+            \@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
+          }
+          {
+            \int_case:nnF \tex_currentgrouptype:D
+              {
+                { 16 }
+                  {
+                    \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+                    \@@_back_input_gtl:N \l_@@_after_group_gtl
+                    \tl_if_head_eq_meaning:nNTF \l_@@_head_tl \tex_middle:D
+                      {
+                        \tl_use:N \l_@@_head_tl \scan_stop:
+                        \gtl_clear:N \l_@@_after_group_gtl
+                      }
+                      { \tl_use:N \l_@@_head_tl \scan_stop: }
+                    \@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
+                  }
+                { 15 }
+                  { % todo: this is a TeX error
+                    \tl_use:N \l_@@_head_tl \scan_stop:
+                  }
+              }
+              { \@@_off_save: }
+          }
+      }
+  }
+\cs_new_protected:Npn \@@_scan_delimiter:
+  {
+    \@@_get_x_non_relax:
+    \@@_set_cmd:
+    \int_case:nnF \l_@@_head_cmd_int
+      {
+        { \@@_tex_use:n { the_char } }
+          { \@@_prev_input:V \l_@@_head_tl }
+        { \@@_tex_use:n { other_char } }
+          { \@@_prev_input:V \l_@@_head_tl }
+        { \@@_tex_use:n { delim_num } }
+          {
+            \@@_prev_input:V \l_@@_head_tl
+            \@@_scan_int:
+          }
+      }
+      {
+        \@@_back_input:
+        \@@_tex_error:nV { missing-delim } \l_@@_head_tl
+        \@@_prev_input:n { . }
+      }
+  }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { math_comp }                            % 50
-  { \@@_not_implemented:n { math~comp } }
+  { \@@_mode_math:n { \@@_sub_sup: } }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { limit_switch }                         % 51
-  { \@@_not_implemented:n { limits } }
+  { \@@_mode_math:n { \@@_output_head_token: } }
+\cs_new_protected:Npn \@@_output_head_token:
+  {
+    \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+    \l_@@_head_token
+    \@@_print_action:
+  }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { above }                                % 52
-  { \@@_not_implemented:n { above } }
+  { \@@_mode_math:n { \@@_not_implemented:n { above } } }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { math_style }                           % 53
-  { \@@_not_implemented:n { math~style } }
+  { \@@_mode_math:n { \@@_output_head_token: } }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { math_choice }                          % 54
-  { \@@_not_implemented:n { math~choice } }
+  { \@@_mode_math:n { \@@_do_choice: } }
+\cs_new_protected:Npn \@@_do_choice:
+  {
+    \@@_prev_input_gpush:N \l_@@_head_tl
+    \@@_print_action:
+    \@@_scan_left_brace:
+    \@@_prev_input_gpop:N \l_@@_head_tl
+    \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
+    \gtl_gconcat:NNN \g_@@_output_gtl
+      \g_@@_output_gtl \c_group_begin_gtl
+    \tl_use:N \l_@@_head_tl \c_group_begin_token
+    \gtl_clear:N \l_@@_after_group_gtl
+    \int_set:Nn \l_@@_choice_int { 1 }
+    \@@_print_action:x
+      { \tl_to_str:N \l_@@_head_tl \iow_char:N \{ }
+  }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { non_script }                           % 55
-  { \@@_not_implemented:n { non~script } }
+  { \@@_mode_math:n { \@@_output_head_token: } }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { vcenter }                              % 56
-  { \@@_not_implemented:n { vcenter } }
+  { \@@_mode_math:n { \@@_not_implemented:n { vcenter } } }
 %    \end{macrocode}
 %
 % \subsubsection{From 57 to 70}
@@ -5953,7 +6312,7 @@
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { omit }                                 % 63
-  { \@@_not_implemented:n { omit } }
+  { \l_@@_head_token \@@_print_action: }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
@@ -5974,19 +6333,7 @@
 %
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { radical }                              % 66
-  {
-    \@@_mode_math:n
-      {
-        \@@_prev_input_gpush:N \l_@@_head_tl
-        \@@_print_action:
-        \@@_scan_int:
-        \@@_scan_math:
-        \@@_prev_input_gpop:N \l_@@_head_tl
-        \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
-        \tl_use:N \l_@@_head_tl \scan_stop:
-        \@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
-      }
-  }
+  { \@@_mode_math:n { \@@_do_math_accent: } }
 %    \end{macrocode}
 %
 %    \begin{macrocode}
@@ -6315,7 +6662,11 @@
             \int_case:nnF \l_@@_head_char_int
               {
                 { 7 } { \@@_scan_extension_operands_aux: } % pdfobj
-                { 9 } { \@@_scan_extension_operands_aux: } % pdfxform
+                { 9 }
+                  {
+                    \@@_prepare_mag:
+                    \@@_scan_extension_operands_aux:
+                  } % pdfxform
                 { 11 } { \@@_scan_extension_operands_aux: } %pdfximage
               }
               { \@@_scan_immediate_operands_bad: }
@@ -6455,6 +6806,7 @@
 %
 % \begin{macro}{\@@_after_assignment:}
 % \begin{macro}{\@@_omit_after_assignment:w}
+%   ^^A todo: simplify
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_after_assignment:
   {
@@ -6705,7 +7057,6 @@
   }
 %    \end{macrocode}
 %
-% ^^A todo: print the temporary relax assignment?
 %    \begin{macrocode}
 \@@_prefixed_new:nn { shorthand_def }                       % 95
   {
@@ -6716,6 +7067,7 @@
     \@@_print_action:x
       { \l_@@_prev_action_tl \tl_to_str:N \l_@@_defined_tl }
     \exp_after:wN \cs_set_eq:NN \l_@@_defined_tl \scan_stop:
+    \@@_just_print_assigned_token:
     \@@_scan_optional_equals:
     \@@_scan_int:
     \@@_assign_token:n { }
@@ -6838,7 +7190,6 @@
   }
 %    \end{macrocode}
 %
-% ^^A todo: print the temporary nullfont assignment?
 %    \begin{macrocode}
 \@@_prefixed_new:nn { letterspace_font }                    % 101
   {
@@ -6848,6 +7199,7 @@
     \@@_print_action:x
       { \g_@@_action_text_str \tl_to_str:N \l_@@_defined_tl }
     \exp_after:wN \cs_set_eq:NN \l_@@_defined_tl \@@_nullfont:
+    \@@_just_print_assigned_token:
     \@@_scan_optional_equals:
     \@@_scan_font_ident:
     \@@_scan_int:
@@ -6855,7 +7207,6 @@
   }
 %    \end{macrocode}
 %
-% ^^A todo: print the temporary nullfont assignment?
 %    \begin{macrocode}
 \@@_prefixed_new:nn { pdf_copy_font }                       % 102
   {
@@ -6865,6 +7216,7 @@
     \@@_print_action:x
       { \g_@@_action_text_str \tl_to_str:N \l_@@_defined_tl }
     \exp_after:wN \cs_set_eq:NN \l_@@_defined_tl \@@_nullfont:
+    \@@_just_print_assigned_token:
     \@@_scan_optional_equals:
     \@@_scan_font_ident:
     \@@_assign_token:n { }
@@ -7013,13 +7365,14 @@
 % \item |no_expand=105| for \tn{noexpand} and \tn{pdfprimitive}.
 % \item |input=106| for \tn{input}, \tn{endinput} and \tn{scantokens}.
 % \item |if_test=107| for the conditionals, \tn{if}, \tn{ifcat},
-%   \tn{ifnum}, \tn{ifdim}, \tn{ifodd}, \tn{ifvmode}, \tn{ifhmode},
-%   \tn{ifmmode}, \tn{ifinner}, \tn{ifvoid}, \tn{ifhbox}, \tn{ifvbox},
+%   \tn{ifnum}, \tn{ifdim}, \tn{ifodd}, \tn[index=ifhmode]{if[vhm]mode},
+%   \tn[index=iftdir]{if[tydm]dir},
+%   \tn{ifinner}, \tn{ifvoid}, \tn[index=ifhbox]{if[hvtydm]box},
 %   \tn{ifx}, \tn{ifeof}, \tn{iftrue}, \tn{iffalse}, \tn{ifcase},
 %   \tn{ifdefined}, \tn{ifcsname}, \tn{iffontchar}, \tn{ifincsname},
-%   \tn{ifpdfprimitive}, \tn{ifpdfabsnum}, and \tn{ifpdfabsdim}.
+%   \tn{ifprimitive}, \tn{ifabsnum}, \tn{ifabsdim}, \tn{ifjfont}, \tn{iftfont}.
 % \item |fi_or_else=108| for \tn{fi}, \tn{else} and \tn{or}.
-% \item |cs_name=109| for \tn{csname}.
+% \item |cs_name=109| for \tn{csname} and \tn{lastnamedcs}.
 % \item |convert=110| for \tn{number}, \tn{romannumeral}, \tn{string},
 %   \tn{meaning}, \tn{fontname}, \tn{eTeXrevision}, \tn{pdftexrevision},
 %   \tn{pdftexbanner}, \tn{pdffontname}, \tn{pdffontobjnum},
@@ -7066,7 +7419,7 @@
     \@@_token_if_expandable:NTF \l_@@_head_token
       { \@@_expand_do:N \prg_do_nothing: }
       { \@@_back_input: }
-    \@@_prev_input_gpop:N \l_@@_head_gtl
+    \@@_prev_input_gpop_gtl:N \l_@@_head_gtl
     \@@_set_action_text:x
       { back_input: ~ \gtl_to_str:N \l_@@_head_gtl }
     \gtl_pop_left:N \l_@@_head_gtl
@@ -7214,12 +7567,21 @@
 %    \begin{macrocode}
 \@@_new_tex_expandable:nn { cs_name }                       % 109
   {
-    \@@_prev_input_gpush:N \l_@@_head_tl
-    \@@_print_expansion:
-    \@@_csname_loop:
-    \@@_prev_input_silent:V \l_@@_head_tl
-    \@@_prev_input_gpop:N \l_@@_head_tl
-    \@@_back_input_tl_o:
+    \int_compare:nNnTF \l_@@_head_char_int = 0
+      {
+        \@@_prev_input_gpush:N \l_@@_head_tl
+        \@@_print_expansion:
+        \@@_csname_loop:
+        \@@_prev_input_silent:V \l_@@_head_tl
+        \@@_get_lastnamedcs:
+        \@@_prev_input_gpop:N \l_@@_head_tl
+        \@@_back_input_tl_o:
+      }
+      {
+        \@@_back_input:V \g_@@_lastnamedcs_tl
+        \@@_print_expansion:x
+          { \tl_to_str:N \l_@@_head_tl = \tl_to_str:N \g_@@_lastnamedcs_tl }
+      }
   }
 \cs_new_protected:Npn \@@_csname_loop:
   {
@@ -7239,6 +7601,14 @@
         \@@_csname_loop:
       }
   }
+\cs_new_protected:Npn \@@_get_lastnamedcs:
+  {
+    \group_begin:
+    \@@_prev_input_get:N \l_@@_head_tl
+    \tl_gset:No \g_@@_lastnamedcs_tl
+      { \cs:w \exp_after:wN \use_none:n \l_@@_head_tl }
+    \group_end:
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -7252,7 +7622,7 @@
         0      \@@_scan_int:
         1      \@@_scan_int:
         2      \@@_convert_string:
-        3      \@@_convert_meaning:
+        3      \@@_convert_meaning:w
         4      \@@_scan_font_ident:
         8      \@@_scan_font_ident:
         9      \@@_scan_font_ident:
@@ -7300,12 +7670,28 @@
       { \@@_prev_input:x { \gtl_to_str:N \l_@@_head_gtl } }
       { \@@_prev_input:V \l_@@_head_tl }
   }
-\cs_new_protected:Npn \@@_convert_meaning:
+\cs_new_protected:Npn \@@_convert_meaning:w
+    \@@_prev_input_gpop:N \l_@@_head_tl \@@_back_input_tl_o:
   {
     \@@_get_next:
     \tl_if_empty:NTF \l_@@_head_tl
-      { \@@_prev_input:n { \l_@@_head_token } }
-      { \@@_prev_input:V \l_@@_head_tl }
+      {
+        \gtl_set_eq:NN \l_@@_tmpb_gtl \l_@@_head_gtl
+        \@@_prev_input_gpop:N \l_@@_prev_input_tl
+        \exp_args:NNV \gtl_put_left:Nn \l_@@_tmpb_gtl \l_@@_prev_input_tl
+        \@@_prev_input_gpush_gtl:N \l_@@_tmpb_gtl
+        \@@_print_action:x { \gtl_to_str:N \l_@@_tmpb_gtl }
+        \@@_prev_input_gpop_gtl:N \l_@@_tmpb_gtl
+        \tl_set:Nx \l_@@_tmpa_tl { \gtl_head_do:NN \l_@@_head_gtl \tex_meaning:D }
+        \@@_back_input:V \l_@@_tmpa_tl
+        \@@_print_expansion:x
+          { \gtl_to_str:N \l_@@_tmpb_gtl = \tl_to_str:N \l_@@_tmpa_tl }
+      }
+      {
+        \@@_prev_input:V \l_@@_head_tl
+        \@@_prev_input_gpop:N \l_@@_head_tl
+        \@@_back_input_tl_o:
+      }
   }
 \cs_new_protected:Npn \@@_scan_pdfstrcmp:
   {
@@ -7372,7 +7758,7 @@
       }
       { % \the
         \@@_get_x_next:
-        \@@_scan_something_internal:n { 5 }
+        \@@_rescan_something_internal:n { 5 }
         \@@_prev_input_gpop:N \l_@@_head_tl
         \@@_set_action_text:x
           {
@@ -7412,10 +7798,7 @@
 %
 %    \begin{macrocode}
 \@@_new_tex_expandable:nn { end_template }                  % 117
-  {
-    \@@_not_implemented:n { end-template } { } { } { }
-    \@@_back_input_tl_o:
-  }
+  { \@@_back_input_tl_o: }
 %    \end{macrocode}
 %
 %
@@ -7518,6 +7901,7 @@
   }
 \cs_new_protected:Npn \@@_cond_pop:
   {
+    \fi:
     \int_gset:Nn \g_@@_if_limit_int
       { \tl_head:N \g_@@_if_limit_tl }
     \tl_gset:Nx \g_@@_if_limit_tl
@@ -7567,7 +7951,8 @@
         {  1 } { \@@_test_two_chars:nn { 1 } {#1} } % ifcat
         { 12 } { \@@_test_ifx:n {#1} }
         { 16 } { \@@_test_case:n {#1} }
-        { 21 } { \@@_test_pdfprimitive:n {#1} } % ^^A todo and \unless
+        { 20 } { \if_true: \@@_test_incsname:n {#1} }
+        { 21 } { \if_true: \@@_test_pdfprimitive:n {#1} }
       }
       {
         \@@_prev_input_gpush:N \l_@@_head_tl
@@ -7579,13 +7964,8 @@
             {  3 } % ifdim
               { \@@_test_two_vals:N \@@_scan_normal_dimen: }
             {  4 } { \@@_scan_int: } % ifodd
-            % {  5 } { } % ifvmode
-            % {  6 } { } % ifhmode
-            % {  7 } { } % ifmmode
-            % {  8 } { } % ifinner
-            {  9 } { \@@_scan_int: } % ifvoid
-            { 10 } { \@@_scan_int: } % ifhbox
-            { 11 } { \@@_scan_int: } % ifvbox
+            % {  5 } { } % if[hvm]mode, ifinner, if[tydm]dir
+            {  9 } { \@@_scan_int: } % ifvoid, ifhbox, ifvbox etc
             { 13 } { \@@_scan_int: } % ifeof
             % { 14 } { } % iftrue
             % { 15 } { } % iffalse
@@ -7593,18 +7973,18 @@
             { 18 } { \@@_test_ifcsname: } % ifcsname
             { 19 } % iffontchar
               { \@@_scan_font_ident: \@@_scan_int: }
-            % { 20 } { } % ifincsname % ^^A todo: something?
-            { 22 } % ifpdfabsnum
+            { 22 } % ifabsnum
               { \@@_test_two_vals:N \@@_scan_int: }
-            { 23 } % ifpdfabsdim
+            { 23 } % ifabsdim
               { \@@_test_two_vals:N \@@_scan_normal_dimen: }
+            { 24 } { \@@_scan_font_ident: } % ifjfont, iftfont
           }
         \@@_prev_input_gpop:N \l_@@_head_tl
         \@@_set_action_text:x { \tl_to_str:N \l_@@_head_tl }
         \l_@@_head_tl \scan_stop:
-          \exp_after:wN \@@_cond_true:n
+          \@@_cond_true:NNNn
         \else:
-          \exp_after:wN \@@_cond_false:n
+          \@@_cond_false:Nn
         \fi:
         {#1}
       }
@@ -7612,11 +7992,11 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_cond_true:n}
+% \begin{macro}{\@@_cond_true:NNNn}
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_cond_true:n #1
+\cs_new_protected:Npn \@@_cond_true:NNNn #1#2#3#4
   {
-    \@@_change_if_limit:nn { 3 } {#1} % wait for else/fi
+    \@@_change_if_limit:nn { 3 } {#4} % wait for else/fi
     \@@_print_expansion:x { \g_@@_action_text_str = true }
   }
 %    \end{macrocode}
@@ -7623,11 +8003,11 @@
 % \end{macro}
 %
 % \begin{macro}
-%   {\@@_cond_false:n, \@@_cond_false_loop:n, \@@_cond_false_common:}
+%   {\@@_cond_false:Nn, \@@_cond_false_loop:n, \@@_cond_false_common:}
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_cond_false:n #1
+\cs_new_protected:Npn \@@_cond_false:Nn #1#2
   {
-    \@@_cond_false_loop:n {#1}
+    \@@_cond_false_loop:n {#2}
     \@@_cond_false_common:
     \@@_print_expansion:x
       {
@@ -7683,6 +8063,7 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_test_two_chars:nn #1
   {
+    \exp_args:NNo \gtl_set:Nn \l_@@_head_gtl { \l_@@_head_tl }
     \@@_prev_input_gpush_gtl:N \l_@@_head_gtl
     \@@_print_expansion:
     \@@_test_two_chars_get:n {#1}
@@ -7690,13 +8071,18 @@
     \@@_prev_input_gpop_gtl:N \l_@@_head_gtl
     \@@_set_action_text:x { \gtl_to_str:N \l_@@_head_gtl }
     \gtl_pop_left_item:NNTF \l_@@_head_gtl \l_@@_head_tl { } { }
+    \exp_args:No \tl_if_head_eq_meaning:nNT \l_@@_head_tl \reverse_if:N
+      {
+        \gtl_pop_left_item:NNTF \l_@@_head_gtl \l_@@_head_tl { } { }
+        \tl_put_left:Nn \l_@@_head_tl { \reverse_if:N }
+      }
     \gtl_pop_left:NN \l_@@_head_gtl \l_@@_tmpb_gtl
     \@@_test_two_chars_gtl:N \l_@@_tmpb_gtl
     \@@_test_two_chars_gtl:N \l_@@_head_gtl
     \l_@@_head_tl \scan_stop:
-      \exp_after:wN \@@_cond_true:n
+      \@@_cond_true:NNNn
     \else:
-      \exp_after:wN \@@_cond_false:n
+      \@@_cond_false:Nn
     \fi:
   }
 \cs_new_protected:Npn \@@_test_two_chars_get:n #1
@@ -7758,9 +8144,9 @@
       }
     \@@_test_ifx_aux:NNN \l_@@_tmpb_token \l_@@_tmpb_gtl
       \@@_test_ifx_aux:w
-      \exp_after:wN \@@_cond_true:n
+      \@@_cond_true:NNNn
     \else:
-      \exp_after:wN \@@_cond_false:n
+      \@@_cond_false:Nn
     \fi:
     {#1}
   }
@@ -7788,9 +8174,11 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_test_case:n, \@@_test_case_aux:nn}
+% ^^A todo: \ifcase\currentifbranch\show 0\or\show 1\else\show -\fi won't work correctly.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_test_case:n #1
   {
+    \if_case:w 0 ~
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_expansion:
     \bool_if:NT \g_@@_internal_debug_bool { \iow_term:n { {\ifcase level~#1} } }
@@ -7798,6 +8186,12 @@
     \@@_prev_input_get:N \l_@@_head_tl
     \tl_set:Nx \l_@@_head_tl { \tl_tail:N \l_@@_head_tl }
     % ^^A does text_case_aux use prev_input_seq?
+    \int_compare:nNnF { \l_@@_head_tl } = 0
+      {
+        \int_compare:nNnTF { \l_@@_head_tl } > 0
+          { \fi: \if_case:w 1 ~ \or: }
+          { \fi: \if_case:w -1 ~ \else: }
+      }
     \exp_args:No \@@_test_case_aux:nn { \l_@@_head_tl } {#1}
     \@@_prev_input_gpop:N \l_@@_head_tl
     \@@_print_expansion:x { \tl_to_str:N \l_@@_head_tl }
@@ -7827,6 +8221,20 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_test_incsname:n}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_test_incsname:n #1
+  { \@@_not_implemented:n { ifincsname } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_test_pdfprimitive:n}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_test_pdfprimitive:n #1
+  { \@@_not_implemented:n { ifpdfprimitive } }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\@@_test_ifdefined:}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_test_ifdefined:
@@ -7857,6 +8265,7 @@
   {
     \@@_csname_loop:
     \@@_prev_input:V \l_@@_head_tl
+    \@@_get_lastnamedcs:
   }
 %    \end{macrocode}
 % \end{macro}
@@ -8036,8 +8445,8 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_print_state_prev:
   {
-    \seq_set_map:NNn \l_@@_tmpa_seq \g_@@_prev_input_seq
-      { \@@_to_str:n {##1} }
+    \seq_set_map_x:NNn \l_@@_tmpa_seq \g_@@_prev_input_seq
+      { \@@_to_str:Nn ##1 }
     \seq_remove_all:Nn \l_@@_tmpa_seq { }
     \seq_if_empty:NTF \l_@@_tmpa_seq
       { \@@_print_message:nn { || ~ } { } }
@@ -8140,21 +8549,25 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_print_assigned_token:, \@@_print_assigned_register:}
+% \begin{macro}{\@@_just_print_assigned_token:, \@@_print_assigned_token:, \@@_print_assigned_register:}
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_print_assigned_token:
+\cs_new_protected:Npn \@@_just_print_assigned_token:
   {
-    \@@_after_assignment: % ^^A todo: simplify
     \@@_print_assignment:x
       {
         Set~ \exp_after:wN \token_to_str:N \l_@@_defined_tl
         = \exp_after:wN \token_to_meaning:N \l_@@_defined_tl
       }
+  }
+\cs_new_protected:Npn \@@_print_assigned_token:
+  {
+    \@@_after_assignment:
+    \@@_just_print_assigned_token:
     \@@_omit_after_assignment:w
   }
 \cs_new_protected:Npn \@@_print_assigned_register:
   {
-    \@@_after_assignment: % ^^A todo: simplify
+    \@@_after_assignment:
     \@@_exp_args:Nx \@@_print_assignment:x
       {
         \exp_not:n
@@ -8512,8 +8925,9 @@
     max-input        .int_gset:N  = \g_@@_default_max_input_int ,
     number-steps     .bool_gset:N = \g_@@_default_number_steps_bool ,
     online           .int_gset:N  = \g_@@_default_online_int ,
-    prompt-input     .clist_gset:N = \g_@@_default_prompt_input_clist ,
-    trace-assigns    .bool_gset:N = \g_@@_default_trace_assign_bool ,
+    prompt-input     .code:n
+      = \@@_prompt_input:Nn \g_@@_default_prompt_input_clist {#1} ,
+    trace-assigns    .bool_gset:N = \g_@@_default_trace_assigns_bool ,
     trace-expansion  .bool_gset:N = \g_@@_default_trace_expansion_bool ,
     trace-other      .bool_gset:N = \g_@@_default_trace_other_bool ,
     welcome-message  .bool_gset:N = \g_@@_default_welcome_message_bool ,
@@ -8527,7 +8941,8 @@
     max-input        .int_gset:N  = \g_@@_max_input_int ,
     number-steps     .bool_gset:N = \g_@@_number_steps_bool ,
     online           .int_gset:N  = \g_@@_online_int ,
-    prompt-input     .clist_gset:N = \g_@@_prompt_input_clist ,
+    prompt-input     .code:n
+      = \@@_prompt_input:Nn \g_@@_prompt_input_clist {#1} ,
     trace-assigns    .bool_gset:N = \g_@@_trace_assigns_bool ,
     trace-expansion  .bool_gset:N = \g_@@_trace_expansion_bool ,
     trace-other      .bool_gset:N = \g_@@_trace_other_bool ,
@@ -8620,7 +9035,6 @@
     \@@_exit_point:
     \@@_print_outcome:
     \@@_final_test:
-    \@@_final_after_assignment:
     \@@_exit_point:
   }
 \cs_new_protected:Npn \unravel_get:nnN #1#2#3
@@ -8637,6 +9051,7 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_init_key_vars:
   {
+    \sys_if_engine_luatex:T { \tl_gset:No \g_@@_lastnamedcs_tl { \tex_lastnamedcs:D } }
     \bool_gset_eq:NN \g_@@_explicit_prompt_bool \g_@@_default_explicit_prompt_bool
     \bool_gset_eq:NN \g_@@_internal_debug_bool \g_@@_default_internal_debug_bool
     \bool_gset_eq:NN \g_@@_number_steps_bool \g_@@_default_number_steps_bool
@@ -8725,15 +9140,18 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_final_test:
   {
-    \bool_if:nTF
+    \@@_input_if_empty:TF
       {
-        \tl_if_empty_p:N \g_@@_if_limit_tl
-        && \int_compare_p:nNn \g_@@_if_limit_int = 0
-        && \int_compare_p:nNn \g_@@_if_depth_int = 0
-        && \seq_if_empty_p:N \g_@@_prev_input_seq
+        \seq_if_empty:NTF \g_@@_prev_input_seq
+          {
+            \tl_if_empty:NTF \g_@@_if_limit_tl
+              { \int_compare:nNnF \g_@@_if_limit_int = 0 { \@@_final_bad: } }
+              { \@@_final_conditionals: }
+          }
+          { \@@_final_bad: }
       }
-      { \@@_input_if_empty:TF { } { \@@_final_bad: } }
       { \@@_final_bad: }
+    \@@_final_after_assignment:
   }
 \cs_new_protected:Npn \@@_final_bad:
   {
@@ -8740,6 +9158,28 @@
     \@@_error:nnnnn { internal }
       { the-last-unravel-finished-badly } { } { } { }
   }
+\cs_new_protected:Npn \@@_final_conditionals:
+  {
+    \group_begin:
+    \msg_warning:nnx { unravel } { dangling-conditionals }
+      { \tl_count:N \g_@@_if_limit_tl }
+    \group_end:
+    \tl_greverse:N \g_@@_if_limit_tl
+    \tl_gput_right:NV \g_@@_if_limit_tl \g_@@_if_limit_int
+    \tl_gset:Nx \g_@@_if_limit_tl { \tl_tail:N \g_@@_if_limit_tl } % remove the {0}
+    \prg_replicate:nn { \tl_count:N \g_@@_if_limit_tl } { \fi: }
+    \tl_map_function:NN \g_@@_if_limit_tl \@@_final_cond_aux:n
+  }
+\cs_new:Npn \@@_final_cond_aux:n #1
+  {
+    \int_case:nnF {#1}
+      {
+        { 2 } { \if_false: \else: }
+        { 3 } { \if_true: }
+        { 4 } { \if_case:w 0 ~ }
+      }
+      { \@@_final_bad: }
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -8757,6 +9197,12 @@
 % \subsection{Messages}
 %
 %    \begin{macrocode}
+\msg_new:nnnn { unravel } { prev-input }
+  { Internal~error:~unexpected~type~of~``prev_input''~entry. }
+  {
+    Found~type~#2~instead~of~#1~to~assign~to~variable~#3.~Contents:\\
+    \iow_indent:n {#4}
+  }
 \msg_new:nnn { unravel } { unknown-primitive }
   { Internal~error:~the~primitive~'#1'~is~not~known. }
 \msg_new:nnn { unravel } { extra-fi-or-else }
@@ -8847,6 +9293,8 @@
     Some~TeX~command~expects~input~beyond~the~end~of~
     the~argument~of~\iow_char:N\\unravel.
   }
+\msg_new:nnn { unravel } { dangling-conditionals }
+  { Attempting~to~issue~#1~dangling~conditionals. }
 %    \end{macrocode}
 %
 % Some error messages from \TeX{} itself.
@@ -8932,6 +9380,17 @@
     not~appear~between~\token_to_str:c{csname}~and~
     \token_to_str:c{endcsname}.
   }
+\@@_tex_msg_new:nnn { missing-delim }
+  { Missing~delimiter~(.~inserted) }
+  {
+    I~was~expecting~to~see~something~like~`('~or~`\token_to_str:N\{'~or~
+    `\token_to_str:N\}'~here.~If~you~typed,~e.g.,~
+    `\{'~instead~of~`\token_to_str:N\{',~you~
+    should~probably~delete~the~`\{'~by~typing~`1'~now,~so~that~
+    braces~don't~get~unbalanced.~Otherwise~just~proceed.~
+    Acceptable~delimiters~are~characters~whose~\token_to_str:c{delcode}~is~
+    nonnegative,~or~you~can~use~`\token_to_str:c{delimiter}~<delimiter~code>'.
+  }
 %    \end{macrocode}
 %
 % Fatal \TeX{} error messages.

Modified: trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty	2021-05-12 20:02:13 UTC (rev 59174)
+++ trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty	2021-05-12 20:04:18 UTC (rev 59175)
@@ -11,7 +11,7 @@
 %% Communicate any suggestions for changing this package
 %% to Bruno Le Floch (blflatex+unravel at gmail.com).
 %% 
-%% File: unravel.dtx Copyright (C) 2013, 2015, 2018-2019 Bruno Le Floch
+%% File: unravel.dtx Copyright (C) 2013, 2015, 2018-2019, 2021 Bruno Le Floch
 %%
 %% It may be distributed and/or modified under the conditions of the
 %% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -146,7 +146,7 @@
     \newlinechar  = 10 ~
   }
 \expandafter \endgroup \__unravel_setup_latexe:
-\RequirePackage{expl3,xparse}[2018/02/21]
+\RequirePackage{expl3,xparse}[2021/01/01]
 \RequirePackage{gtl}[2018/12/28]
 \csname cs_if_exist:cF\endcsname{str_range:nnn}{\RequirePackage{l3str}}
 \csname use:n\endcsname
@@ -153,9 +153,13 @@
   {%
     \csname __unravel_setup_restore:\endcsname
     \ProvidesExplPackage
-      {unravel} {2019/11/15} {0.2h} {Watching TeX digest tokens}%
+      {unravel} {2021/05/11} {0.3a} {Watching TeX digest tokens}%
     \csname __unravel_setup_unravel:\endcsname
   }%
+\cs_gset:Npn \group_align_safe_begin:
+  { \exp:w \if_false: { \fi: -`} \exp_stop_f: }
+\cs_gset:Npn \group_align_safe_end:
+  { \if_int_compare:w `{ = \c_zero_int } \fi: }
 \cs_new_eq:NN \__unravel_currentgrouptype:      \tex_currentgrouptype:D
 \cs_new_protected:Npn \__unravel_set_escapechar:n
   { \int_set:Nn \tex_escapechar:D }
@@ -176,6 +180,7 @@
 \cs_generate_variant:Nn \tl_to_str:n { o }
 \cs_generate_variant:Nn \tl_if_eq:nnTF { o }
 \cs_generate_variant:Nn \tl_if_head_eq_meaning:nNT { V }
+\cs_generate_variant:Nn \tl_if_head_eq_meaning:nNTF { V }
 \cs_generate_variant:Nn \tl_if_single_token:nT { V }
 \cs_generate_variant:Nn \gtl_gput_right:Nn { NV }
 \cs_generate_variant:Nn \gtl_if_empty:NTF { c }
@@ -249,23 +254,27 @@
       }
     #1
   }
-\cs_new_protected:Npn \__unravel_prepare_mag:
+\cs_new:Npn \__unravel_use_ii_i:nn #1#2 { #2 #1 }
+\cs_new_protected:Npn \__unravel_prompt_input:Nn #1#2
   {
-    \int_compare:nNnT { \g__unravel_mag_set_int } > { 0 }
-      {
-        \int_compare:nNnF { \__unravel_mag: } = { \g__unravel_mag_set_int }
-          {
-            \__unravel_tex_error:nn { incompatible-mag } { }
-            \int_gset_eq:NN \__unravel_mag: \g__unravel_mag_set_int
-          }
-      }
-    \int_compare:nF { 1 <= \__unravel_mag: <= 32768 }
-      {
-        \__unravel_tex_error:nV { illegal-mag } \l__unravel_head_tl
-        \int_gset:Nn \__unravel_mag: { 1000 }
-      }
-    \int_gset_eq:NN \g__unravel_mag_set_int \__unravel_mag:
+    \clist_gset:Nx #1
+      { \__unravel_prompt_input:w \prg_do_nothing: #2 , \q__unravel_recursion_tail , }
   }
+\cs_new:Npn \__unravel_prompt_input:w #1 ,
+  {
+    \tl_trim_spaces_apply:oN {#1} \__unravel_use_ii_i:nn
+    \__unravel_prompt_input_aux:w ,
+  }
+\cs_new:Npn \__unravel_prompt_input_aux:w #1 ,
+  {
+    \__unravel_use_none_delimit_by_q_recursion_tail:w #1
+      \use_none:nnnnn \q__unravel_recursion_tail
+    { \tl_to_str:n {#1} } ,
+    \__unravel_prompt_input:w \prg_do_nothing:
+  }
+\cs_new:Npn \__unravel_use_none_delimit_by_q_recursion_tail:w
+    #1 \q__unravel_recursion_tail { }
+\quark_new:N \q__unravel_recursion_tail
 \cs_new:Npn \__unravel_strip_escape:w
   {
     \tex_romannumeral:D
@@ -275,25 +284,14 @@
 \cs_new:Npn \__unravel_strip_escape_aux:N #1 { \c_zero_int }
 \cs_new:Npn \__unravel_strip_escape_aux:w #1#2
   { - \__unravel_number:w #1 \c_zero_int }
-\cs_new:Npn \__unravel_to_str:n #1
+\cs_new:Npn \__unravel_to_str:Nn #1
   {
-    \tl_if_head_eq_meaning:nNTF {#1} \scan_stop:
-      { \__unravel_to_str_auxi:w #1 ? \q_stop }
-      { \tl_to_str:n }
-    {#1}
+    \if_meaning:w T #1
+      \exp_after:wN \tl_to_str:n
+    \else:
+      \exp_after:wN \gtl_to_str:n
+    \fi:
   }
-\cs_set:Npn \__unravel_tmp:w #1
-  {
-    \cs_new:Npn \__unravel_to_str_auxi:w ##1##2 \q_stop
-      {
-        \exp_after:wN \__unravel_to_str_auxii:w \token_to_str:N ##1 \q_mark
-          #1 tl \q_mark \q_stop
-      }
-    \cs_new:Npn \__unravel_to_str_auxii:w ##1 #1 ##2 \q_mark ##3 \q_stop
-      { \cs_if_exist_use:cF { __unravel_ ##2 _to_str:n } { \tl_to_str:n } }
-  }
-\exp_args:No \__unravel_tmp:w { \tl_to_str:n { s _ _ } }
-\cs_new:Npn \__unravel_gtl_to_str:n { \gtl_to_str:n }
 \cs_new:Npn \__unravel_str_truncate_left:nn #1#2
   {
     \exp_args:Nf \__unravel_str_truncate_left_aux:nnn
@@ -340,6 +338,16 @@
           { \prg_return_true: }
       }
   }
+\cs_new_protected:Npn \__unravel_active_do:nn #1#2
+  {
+    \group_begin:
+    \char_set_active_eq:nN {#1} \scan_stop:
+    \use:x
+      {
+        \group_end:
+        \exp_not:n {#2} { \char_generate:nn {#1} { 13 } }
+      }
+  }
 \cs_new:Npn \__unravel_meaning_to_char:n #1
   { \__unravel_meaning_to_char_auxi:w #1 \q_mark ~ {} ~ \q_mark \q_stop }
 \cs_new:Npn \__unravel_meaning_to_char_auxi:w #1 ~ #2 ~ #3 \q_mark #4 \q_stop
@@ -430,21 +438,46 @@
       }
   }
 \cs_new:Npn \__unravel_prev_input_count_aux:n #1
-  { \tl_if_empty:nF {#1} { + 1 } }
-\cs_new_protected:Npn \__unravel_prev_input_get:N
-  { \seq_get_right:NN \g__unravel_prev_input_seq }
+  { \__unravel_prev_input_count_aux:Nn #1 }
+\cs_new:Npn \__unravel_prev_input_count_aux:Nn #1#2
+  {
+    \if_meaning:w T #1
+      \exp_after:wN \tl_if_empty:nF
+    \else:
+      \exp_after:wN \str_if_eq:onF \exp_after:wN \c_empty_gtl
+    \fi:
+    {#2} { + 1 }
+  }
 \cs_new_protected:Npn \__unravel_prev_input_gpush:
-  { \seq_gput_right:Nn \g__unravel_prev_input_seq { } }
+  { \seq_gput_right:Nn \g__unravel_prev_input_seq { T { } } }
 \cs_new_protected:Npn \__unravel_prev_input_gpush:N
-  { \seq_gput_right:NV \g__unravel_prev_input_seq }
-\cs_new_protected:Npn \__unravel_prev_input_gpop:N
-  { \seq_gpop_right:NN \g__unravel_prev_input_seq }
+  { \__unravel_prev_input_gpush_aux:NN T }
 \cs_new_protected:Npn \__unravel_prev_input_gpush_gtl:
-  { \seq_gput_right:NV \g__unravel_prev_input_seq \c_empty_gtl }
+  { \__unravel_prev_input_gpush_gtl:N \c_empty_gtl }
 \cs_new_protected:Npn \__unravel_prev_input_gpush_gtl:N
-  { \seq_gput_right:NV \g__unravel_prev_input_seq }
+  { \__unravel_prev_input_gpush_aux:NN G }
+\cs_new_protected:Npn \__unravel_prev_input_gpush_aux:NN #1#2
+  { \seq_gput_right:Nx \g__unravel_prev_input_seq { #1 { \exp_not:o {#2} } } }
+\tl_new:N \l__unravel_prev_aux_tl
+\cs_new_protected:Npn \__unravel_prev_input_get:N
+  { \__unravel_prev_input_aux:NNN \seq_get_right:NN T }
+\cs_new_protected:Npn \__unravel_prev_input_gpop:N
+  { \__unravel_prev_input_aux:NNN \seq_gpop_right:NN T }
 \cs_new_protected:Npn \__unravel_prev_input_gpop_gtl:N
-  { \seq_gpop_right:NN \g__unravel_prev_input_seq }
+  { \__unravel_prev_input_aux:NNN \seq_gpop_right:NN G }
+\cs_new_protected:Npn \__unravel_prev_input_aux:NNN #1#2#3
+  {
+    #1 \g__unravel_prev_input_seq \l__unravel_prev_aux_tl
+    \exp_after:wN \__unravel_prev_input_aux:NNNn
+    \exp_after:wN #2 \exp_after:wN #3 \l__unravel_prev_aux_tl
+  }
+\cs_new_protected:Npn \__unravel_prev_input_aux:NNNn #1#2#3
+  {
+    \token_if_eq_meaning:NNTF #1#3
+      { \tl_set:Nn }
+      { \msg_error:nnnnnn { unravel } { prev-input } {#1} {#3} }
+    #2
+  }
 \cs_new_protected:Npn \__unravel_prev_input_silent:n #1
   {
     \__unravel_prev_input_gpop:N \l__unravel_prev_input_tl
@@ -552,6 +585,7 @@
 \tl_new:N \l__unravel_defined_tl
 \tl_new:N \l__unravel_defining_tl
 \cs_new_eq:NN \__unravel_inaccessible:w ?
+\tl_new:N \g__unravel_lastnamedcs_tl
 \gtl_new:N \g__unravel_after_assignment_gtl
 \bool_new:N \g__unravel_set_box_allowed_bool
 \bool_new:N \g__unravel_name_in_progress_bool
@@ -583,6 +617,23 @@
 \tl_const:Nn \c__unravel_point_tl { . }
 \gtl_const:Nx \c__unravel_frozen_relax_gtl { \if_int_compare:w 0 = 0 \fi: }
 \int_new:N \g__unravel_mag_set_int
+\cs_new_protected:Npn \__unravel_prepare_mag:
+  {
+    \int_compare:nNnT { \g__unravel_mag_set_int } > { 0 }
+      {
+        \int_compare:nNnF { \__unravel_mag: } = { \g__unravel_mag_set_int }
+          {
+            \__unravel_tex_error:nn { incompatible-mag } { }
+            \int_gset_eq:NN \__unravel_mag: \g__unravel_mag_set_int
+          }
+      }
+    \int_compare:nF { 1 <= \__unravel_mag: <= 32768 }
+      {
+        \__unravel_tex_error:nV { illegal-mag } \l__unravel_head_tl
+        \int_gset:Nn \__unravel_mag: { 1000 }
+      }
+    \int_gset_eq:NN \g__unravel_mag_set_int \__unravel_mag:
+  }
 \cs_new_protected:Npn \__unravel_tex_const:nn #1#2
   { \int_const:cn { c__unravel_tex_#1_int } {#2} }
 \cs_new:Npn \__unravel_tex_use:n #1 { \int_use:c { c__unravel_tex_#1_int } }
@@ -591,6 +642,12 @@
     \tl_const:cx { c__unravel_tex_#1_tl }
       { { \__unravel_tex_use:n {#2} } {#3} }
   }
+\cs_new_protected:Npn \__unravel_tex_primitive_pdf:nnn #1#2#3
+  {
+    \sys_if_engine_pdftex:F
+      { \__unravel_tex_primitive:nnn {#1} {#2} {#3} }
+    \__unravel_tex_primitive:nnn { pdf #1 } {#2} {#3}
+  }
 \cs_new_protected:Npn \__unravel_new_tex_cmd:nn #1#2
   {
     \cs_new_protected:cpn
@@ -811,6 +868,11 @@
 \__unravel_tex_primitive:nnn { /                 } { ital_corr } { 0 }
 \__unravel_tex_primitive:nnn { accent            } { accent } { 0 }
 \__unravel_tex_primitive:nnn { mathaccent        } { math_accent } { 0 }
+\sys_if_engine_luatex:T
+  {
+    \__unravel_tex_primitive:nnn
+      { explicitdiscretionary } { discretionary } { 1 }
+  }
 \__unravel_tex_primitive:nnn { -                 } { discretionary } { 1 }
 \__unravel_tex_primitive:nnn { discretionary     } { discretionary } { 0 }
 \__unravel_tex_primitive:nnn { eqno              } { eq_no } { 0 }
@@ -854,42 +916,42 @@
 \__unravel_tex_primitive:nnn { special           } { extension } { 3 }
 \__unravel_tex_primitive:nnn { immediate         } { extension } { 4 }
 \__unravel_tex_primitive:nnn { setlanguage       } { extension } { 5 }
-\__unravel_tex_primitive:nnn { pdfliteral        } { extension } { 6 }
-\__unravel_tex_primitive:nnn { pdfobj            } { extension } { 7 }
-\__unravel_tex_primitive:nnn { pdfrefobj         } { extension } { 8 }
-\__unravel_tex_primitive:nnn { pdfxform          } { extension } { 9 }
-\__unravel_tex_primitive:nnn { pdfrefxform       } { extension } { 10 }
-\__unravel_tex_primitive:nnn { pdfximage         } { extension } { 11 }
-\__unravel_tex_primitive:nnn { pdfrefximage      } { extension } { 12 }
-\__unravel_tex_primitive:nnn { pdfannot          } { extension } { 13 }
-\__unravel_tex_primitive:nnn { pdfstartlink      } { extension } { 14 }
-\__unravel_tex_primitive:nnn { pdfendlink        } { extension } { 15 }
-\__unravel_tex_primitive:nnn { pdfoutline        } { extension } { 16 }
-\__unravel_tex_primitive:nnn { pdfdest           } { extension } { 17 }
-\__unravel_tex_primitive:nnn { pdfthread         } { extension } { 18 }
-\__unravel_tex_primitive:nnn { pdfstartthread    } { extension } { 19 }
-\__unravel_tex_primitive:nnn { pdfendthread      } { extension } { 20 }
-\__unravel_tex_primitive:nnn { pdfsavepos        } { extension } { 21 }
-\__unravel_tex_primitive:nnn { pdfinfo           } { extension } { 22 }
-\__unravel_tex_primitive:nnn { pdfcatalog        } { extension } { 23 }
-\__unravel_tex_primitive:nnn { pdfnames          } { extension } { 24 }
-\__unravel_tex_primitive:nnn { pdffontattr       } { extension } { 25 }
-\__unravel_tex_primitive:nnn { pdfincludechars   } { extension } { 26 }
-\__unravel_tex_primitive:nnn { pdfmapfile        } { extension } { 27 }
-\__unravel_tex_primitive:nnn { pdfmapline        } { extension } { 28 }
-\__unravel_tex_primitive:nnn { pdftrailer        } { extension } { 29 }
-\__unravel_tex_primitive:nnn { pdfresettimer     } { extension } { 30 }
-\__unravel_tex_primitive:nnn { pdffontexpand     } { extension } { 31 }
-\__unravel_tex_primitive:nnn { pdfsetrandomseed  } { extension } { 32 }
-\__unravel_tex_primitive:nnn { pdfsnaprefpoint   } { extension } { 33 }
-\__unravel_tex_primitive:nnn { pdfsnapy          } { extension } { 34 }
-\__unravel_tex_primitive:nnn { pdfsnapycomp      } { extension } { 35 }
-\__unravel_tex_primitive:nnn { pdfglyphtounicode } { extension } { 36 }
-\__unravel_tex_primitive:nnn { pdfcolorstack     } { extension } { 37 }
-\__unravel_tex_primitive:nnn { pdfsetmatrix      } { extension } { 38 }
-\__unravel_tex_primitive:nnn { pdfsave           } { extension } { 39 }
-\__unravel_tex_primitive:nnn { pdfrestore        } { extension } { 40 }
-\__unravel_tex_primitive:nnn { pdfnobuiltintounicode } { extension } { 41 }
+\__unravel_tex_primitive_pdf:nnn { literal       } { extension } { 6 }
+\__unravel_tex_primitive_pdf:nnn { obj           } { extension } { 7 }
+\__unravel_tex_primitive_pdf:nnn { refobj        } { extension } { 8 }
+\__unravel_tex_primitive_pdf:nnn { xform         } { extension } { 9 }
+\__unravel_tex_primitive_pdf:nnn { refxform      } { extension } { 10 }
+\__unravel_tex_primitive_pdf:nnn { ximage        } { extension } { 11 }
+\__unravel_tex_primitive_pdf:nnn { refximage     } { extension } { 12 }
+\__unravel_tex_primitive_pdf:nnn { annot         } { extension } { 13 }
+\__unravel_tex_primitive_pdf:nnn { startlink     } { extension } { 14 }
+\__unravel_tex_primitive_pdf:nnn { endlink       } { extension } { 15 }
+\__unravel_tex_primitive_pdf:nnn { outline       } { extension } { 16 }
+\__unravel_tex_primitive_pdf:nnn { dest          } { extension } { 17 }
+\__unravel_tex_primitive_pdf:nnn { thread        } { extension } { 18 }
+\__unravel_tex_primitive_pdf:nnn { startthread   } { extension } { 19 }
+\__unravel_tex_primitive_pdf:nnn { endthread     } { extension } { 20 }
+\__unravel_tex_primitive_pdf:nnn { savepos       } { extension } { 21 }
+\__unravel_tex_primitive_pdf:nnn { info          } { extension } { 22 }
+\__unravel_tex_primitive_pdf:nnn { catalog       } { extension } { 23 }
+\__unravel_tex_primitive_pdf:nnn { names         } { extension } { 24 }
+\__unravel_tex_primitive_pdf:nnn { fontattr      } { extension } { 25 }
+\__unravel_tex_primitive_pdf:nnn { includechars  } { extension } { 26 }
+\__unravel_tex_primitive_pdf:nnn { mapfile       } { extension } { 27 }
+\__unravel_tex_primitive_pdf:nnn { mapline       } { extension } { 28 }
+\__unravel_tex_primitive_pdf:nnn { trailer       } { extension } { 29 }
+\__unravel_tex_primitive_pdf:nnn { resettimer    } { extension } { 30 }
+\__unravel_tex_primitive_pdf:nnn { fontexpand    } { extension } { 31 }
+\__unravel_tex_primitive_pdf:nnn { setrandomseed } { extension } { 32 }
+\__unravel_tex_primitive_pdf:nnn { snaprefpoint  } { extension } { 33 }
+\__unravel_tex_primitive_pdf:nnn { snapy         } { extension } { 34 }
+\__unravel_tex_primitive_pdf:nnn { snapycomp     } { extension } { 35 }
+\__unravel_tex_primitive_pdf:nnn { glyphtounicode} { extension } { 36 }
+\__unravel_tex_primitive_pdf:nnn { colorstack    } { extension } { 37 }
+\__unravel_tex_primitive_pdf:nnn { setmatrix     } { extension } { 38 }
+\__unravel_tex_primitive_pdf:nnn { save          } { extension } { 39 }
+\__unravel_tex_primitive_pdf:nnn { restore       } { extension } { 40 }
+\__unravel_tex_primitive_pdf:nnn { nobuiltintounicode } { extension } { 41 }
 \__unravel_tex_primitive:nnn { openin                } { in_stream } { 1 }
 \__unravel_tex_primitive:nnn { closein               } { in_stream } { 0 }
 \__unravel_tex_primitive:nnn { begingroup            } { begin_group } { 0 }
@@ -905,20 +967,20 @@
 \__unravel_tex_primitive:nnn { lastnodetype          } { last_item } { 3 }
 \__unravel_tex_primitive:nnn { inputlineno           } { last_item } { 4 }
 \__unravel_tex_primitive:nnn { badness               } { last_item } { 5 }
-\__unravel_tex_primitive:nnn { pdftexversion         } { last_item } { 6 }
-\__unravel_tex_primitive:nnn { pdflastobj            } { last_item } { 7 }
-\__unravel_tex_primitive:nnn { pdflastxform          } { last_item } { 8 }
-\__unravel_tex_primitive:nnn { pdflastximage         } { last_item } { 9 }
-\__unravel_tex_primitive:nnn { pdflastximagepages    } { last_item } { 10 }
-\__unravel_tex_primitive:nnn { pdflastannot          } { last_item } { 11 }
-\__unravel_tex_primitive:nnn { pdflastxpos           } { last_item } { 12 }
-\__unravel_tex_primitive:nnn { pdflastypos           } { last_item } { 13 }
-\__unravel_tex_primitive:nnn { pdfretval             } { last_item } { 14 }
-\__unravel_tex_primitive:nnn { pdflastximagecolordepth } { last_item } { 15 }
-\__unravel_tex_primitive:nnn { pdfelapsedtime        } { last_item } { 16 }
-\__unravel_tex_primitive:nnn { pdfshellescape        } { last_item } { 17 }
-\__unravel_tex_primitive:nnn { pdfrandomseed         } { last_item } { 18 }
-\__unravel_tex_primitive:nnn { pdflastlink           } { last_item } { 19 }
+\__unravel_tex_primitive_pdf:nnn { texversion        } { last_item } { 6 }
+\__unravel_tex_primitive_pdf:nnn { lastobj           } { last_item } { 7 }
+\__unravel_tex_primitive_pdf:nnn { lastxform         } { last_item } { 8 }
+\__unravel_tex_primitive_pdf:nnn { lastximage        } { last_item } { 9 }
+\__unravel_tex_primitive_pdf:nnn { lastximagepages   } { last_item } { 10 }
+\__unravel_tex_primitive_pdf:nnn { lastannot         } { last_item } { 11 }
+\__unravel_tex_primitive_pdf:nnn { lastxpos          } { last_item } { 12 }
+\__unravel_tex_primitive_pdf:nnn { lastypos          } { last_item } { 13 }
+\__unravel_tex_primitive_pdf:nnn { retval            } { last_item } { 14 }
+\__unravel_tex_primitive_pdf:nnn { lastximagecolordepth } { last_item } { 15 }
+\__unravel_tex_primitive_pdf:nnn { elapsedtime       } { last_item } { 16 }
+\__unravel_tex_primitive_pdf:nnn { shellescape       } { last_item } { 17 }
+\__unravel_tex_primitive_pdf:nnn { randomseed        } { last_item } { 18 }
+\__unravel_tex_primitive_pdf:nnn { lastlink          } { last_item } { 19 }
 \__unravel_tex_primitive:nnn { eTeXversion           } { last_item } { 20 }
 \__unravel_tex_primitive:nnn { currentgrouplevel     } { last_item } { 21 }
 \__unravel_tex_primitive:nnn { currentgrouptype      } { last_item } { 22 }
@@ -952,10 +1014,10 @@
 \__unravel_tex_primitive:nnn { everyjob              } { assign_toks } { 7 }
 \__unravel_tex_primitive:nnn { everycr               } { assign_toks } { 8 }
 \__unravel_tex_primitive:nnn { errhelp               } { assign_toks } { 9 }
-\__unravel_tex_primitive:nnn { pdfpagesattr          } { assign_toks } { 10 }
-\__unravel_tex_primitive:nnn { pdfpageattr           } { assign_toks } { 11 }
-\__unravel_tex_primitive:nnn { pdfpageresources      } { assign_toks } { 12 }
-\__unravel_tex_primitive:nnn { pdfpkmode             } { assign_toks } { 13 }
+\__unravel_tex_primitive_pdf:nnn { pagesattr         } { assign_toks } { 10 }
+\__unravel_tex_primitive_pdf:nnn { pageattr          } { assign_toks } { 11 }
+\__unravel_tex_primitive_pdf:nnn { pageresources     } { assign_toks } { 12 }
+\__unravel_tex_primitive_pdf:nnn { pkmode            } { assign_toks } { 13 }
 \__unravel_tex_primitive:nnn { everyeof              } { assign_toks } { 14 }
 \__unravel_tex_primitive:nnn { pretolerance          } { assign_int } { 0 }
 \__unravel_tex_primitive:nnn { tolerance             } { assign_int } { 1 }
@@ -1013,38 +1075,38 @@
 \__unravel_tex_primitive:nnn { holdinginserts        } { assign_int } { 53 }
 \__unravel_tex_primitive:nnn { errorcontextlines     } { assign_int } { 54 }
 \__unravel_tex_primitive:nnn { pdfoutput             } { assign_int } { 55 }
-\__unravel_tex_primitive:nnn { pdfcompresslevel      } { assign_int } { 56 }
-\__unravel_tex_primitive:nnn { pdfdecimaldigits      } { assign_int } { 57 }
-\__unravel_tex_primitive:nnn { pdfmovechars          } { assign_int } { 58 }
-\__unravel_tex_primitive:nnn { pdfimageresolution    } { assign_int } { 59 }
-\__unravel_tex_primitive:nnn { pdfpkresolution       } { assign_int } { 60 }
-\__unravel_tex_primitive:nnn { pdfuniqueresname      } { assign_int } { 61 }
-\__unravel_tex_primitive:nnn
-  { pdfoptionalwaysusepdfpagebox    } { assign_int } { 62 }
-\__unravel_tex_primitive:nnn
-  { pdfoptionpdfinclusionerrorlevel } { assign_int } { 63 }
-\__unravel_tex_primitive:nnn
-  { pdfoptionpdfminorversion        } { assign_int } { 64 }
-\__unravel_tex_primitive:nnn { pdfminorversion       } { assign_int } { 64 }
-\__unravel_tex_primitive:nnn { pdfforcepagebox       } { assign_int } { 65 }
-\__unravel_tex_primitive:nnn { pdfpagebox            } { assign_int } { 66 }
-\__unravel_tex_primitive:nnn
-  { pdfinclusionerrorlevel } { assign_int } { 67 }
-\__unravel_tex_primitive:nnn { pdfgamma              } { assign_int } { 68 }
-\__unravel_tex_primitive:nnn { pdfimagegamma         } { assign_int } { 69 }
-\__unravel_tex_primitive:nnn { pdfimagehicolor       } { assign_int } { 70 }
-\__unravel_tex_primitive:nnn { pdfimageapplygamma    } { assign_int } { 71 }
-\__unravel_tex_primitive:nnn { pdfadjustspacing      } { assign_int } { 72 }
-\__unravel_tex_primitive:nnn { pdfprotrudechars      } { assign_int } { 73 }
-\__unravel_tex_primitive:nnn { pdftracingfonts       } { assign_int } { 74 }
-\__unravel_tex_primitive:nnn { pdfobjcompresslevel   } { assign_int } { 75 }
-\__unravel_tex_primitive:nnn
-  { pdfadjustinterwordglue } { assign_int } { 76 }
-\__unravel_tex_primitive:nnn { pdfprependkern        } { assign_int } { 77 }
-\__unravel_tex_primitive:nnn { pdfappendkern         } { assign_int } { 78 }
-\__unravel_tex_primitive:nnn { pdfgentounicode       } { assign_int } { 79 }
-\__unravel_tex_primitive:nnn { pdfdraftmode          } { assign_int } { 80 }
-\__unravel_tex_primitive:nnn { pdfinclusioncopyfonts } { assign_int } { 81 }
+\__unravel_tex_primitive_pdf:nnn { compresslevel     } { assign_int } { 56 }
+\__unravel_tex_primitive_pdf:nnn { decimaldigits     } { assign_int } { 57 }
+\__unravel_tex_primitive_pdf:nnn { movechars         } { assign_int } { 58 }
+\__unravel_tex_primitive_pdf:nnn { imageresolution   } { assign_int } { 59 }
+\__unravel_tex_primitive_pdf:nnn { pkresolution      } { assign_int } { 60 }
+\__unravel_tex_primitive_pdf:nnn { uniqueresname     } { assign_int } { 61 }
+\__unravel_tex_primitive_pdf:nnn
+  { optionalwaysusepdfpagebox    } { assign_int } { 62 }
+\__unravel_tex_primitive_pdf:nnn
+  { optionpdfinclusionerrorlevel } { assign_int } { 63 }
+\__unravel_tex_primitive_pdf:nnn
+  { optionpdfminorversion        } { assign_int } { 64 }
+\__unravel_tex_primitive_pdf:nnn { minorversion      } { assign_int } { 64 }
+\__unravel_tex_primitive_pdf:nnn { forcepagebox      } { assign_int } { 65 }
+\__unravel_tex_primitive_pdf:nnn { pagebox           } { assign_int } { 66 }
+\__unravel_tex_primitive_pdf:nnn
+  { inclusionerrorlevel } { assign_int } { 67 }
+\__unravel_tex_primitive_pdf:nnn { gamma             } { assign_int } { 68 }
+\__unravel_tex_primitive_pdf:nnn { imagegamma        } { assign_int } { 69 }
+\__unravel_tex_primitive_pdf:nnn { imagehicolor      } { assign_int } { 70 }
+\__unravel_tex_primitive_pdf:nnn { imageapplygamma   } { assign_int } { 71 }
+\__unravel_tex_primitive_pdf:nnn { adjustspacing     } { assign_int } { 72 }
+\__unravel_tex_primitive_pdf:nnn { protrudechars     } { assign_int } { 73 }
+\__unravel_tex_primitive_pdf:nnn { tracingfonts      } { assign_int } { 74 }
+\__unravel_tex_primitive_pdf:nnn { objcompresslevel  } { assign_int } { 75 }
+\__unravel_tex_primitive_pdf:nnn
+  { adjustinterwordglue } { assign_int } { 76 }
+\__unravel_tex_primitive_pdf:nnn { prependkern       } { assign_int } { 77 }
+\__unravel_tex_primitive_pdf:nnn { appendkern        } { assign_int } { 78 }
+\__unravel_tex_primitive_pdf:nnn { gentounicode      } { assign_int } { 79 }
+\__unravel_tex_primitive_pdf:nnn { draftmode         } { assign_int } { 80 }
+\__unravel_tex_primitive_pdf:nnn { inclusioncopyfonts } { assign_int } { 81 }
 \__unravel_tex_primitive:nnn { tracingassigns        } { assign_int } { 82 }
 \__unravel_tex_primitive:nnn { tracinggroups         } { assign_int } { 83 }
 \__unravel_tex_primitive:nnn { tracingifs            } { assign_int } { 84 }
@@ -1076,19 +1138,19 @@
 \__unravel_tex_primitive:nnn { hoffset              } { assign_dimen } { 18 }
 \__unravel_tex_primitive:nnn { voffset              } { assign_dimen } { 19 }
 \__unravel_tex_primitive:nnn { emergencystretch     } { assign_dimen } { 20 }
-\__unravel_tex_primitive:nnn { pdfhorigin           } { assign_dimen } { 21 }
-\__unravel_tex_primitive:nnn { pdfvorigin           } { assign_dimen } { 22 }
-\__unravel_tex_primitive:nnn { pdfpagewidth         } { assign_dimen } { 23 }
-\__unravel_tex_primitive:nnn { pdfpageheight        } { assign_dimen } { 24 }
-\__unravel_tex_primitive:nnn { pdflinkmargin        } { assign_dimen } { 25 }
-\__unravel_tex_primitive:nnn { pdfdestmargin        } { assign_dimen } { 26 }
-\__unravel_tex_primitive:nnn { pdfthreadmargin      } { assign_dimen } { 27 }
-\__unravel_tex_primitive:nnn { pdffirstlineheight   } { assign_dimen } { 28 }
-\__unravel_tex_primitive:nnn { pdflastlinedepth     } { assign_dimen } { 29 }
-\__unravel_tex_primitive:nnn { pdfeachlineheight    } { assign_dimen } { 30 }
-\__unravel_tex_primitive:nnn { pdfeachlinedepth     } { assign_dimen } { 31 }
-\__unravel_tex_primitive:nnn { pdfignoreddimen      } { assign_dimen } { 32 }
-\__unravel_tex_primitive:nnn { pdfpxdimen           } { assign_dimen } { 33 }
+\__unravel_tex_primitive_pdf:nnn { horigin          } { assign_dimen } { 21 }
+\__unravel_tex_primitive_pdf:nnn { vorigin          } { assign_dimen } { 22 }
+\__unravel_tex_primitive_pdf:nnn { pagewidth        } { assign_dimen } { 23 }
+\__unravel_tex_primitive_pdf:nnn { pageheight       } { assign_dimen } { 24 }
+\__unravel_tex_primitive_pdf:nnn { linkmargin       } { assign_dimen } { 25 }
+\__unravel_tex_primitive_pdf:nnn { destmargin       } { assign_dimen } { 26 }
+\__unravel_tex_primitive_pdf:nnn { threadmargin     } { assign_dimen } { 27 }
+\__unravel_tex_primitive_pdf:nnn { firstlineheight  } { assign_dimen } { 28 }
+\__unravel_tex_primitive_pdf:nnn { lastlinedepth    } { assign_dimen } { 29 }
+\__unravel_tex_primitive_pdf:nnn { eachlineheight   } { assign_dimen } { 30 }
+\__unravel_tex_primitive_pdf:nnn { eachlinedepth    } { assign_dimen } { 31 }
+\__unravel_tex_primitive_pdf:nnn { ignoreddimen     } { assign_dimen } { 32 }
+\__unravel_tex_primitive_pdf:nnn { pxdimen          } { assign_dimen } { 33 }
 \__unravel_tex_primitive:nnn { lineskip              } { assign_glue } { 0 }
 \__unravel_tex_primitive:nnn { baselineskip          } { assign_glue } { 1 }
 \__unravel_tex_primitive:nnn { parskip               } { assign_glue } { 2 }
@@ -1114,7 +1176,7 @@
 \__unravel_tex_primitive:nnn { rpcode           } { assign_font_int } { 3 }
 \__unravel_tex_primitive:nnn { efcode           } { assign_font_int } { 4 }
 \__unravel_tex_primitive:nnn { tagcode          } { assign_font_int } { 5 }
-\__unravel_tex_primitive:nnn { pdfnoligatures   } { assign_font_int } { 6 }
+\__unravel_tex_primitive_pdf:nnn { noligatures  } { assign_font_int } { 6 }
 \__unravel_tex_primitive:nnn { knbscode         } { assign_font_int } { 7 }
 \__unravel_tex_primitive:nnn { stbscode         } { assign_font_int } { 8 }
 \__unravel_tex_primitive:nnn { shbscode         } { assign_font_int } { 9 }
@@ -1187,12 +1249,12 @@
 \__unravel_tex_primitive:nnn { scrollmode      } { set_interaction } { 2 }
 \__unravel_tex_primitive:nnn { errorstopmode   } { set_interaction } { 3 }
 \__unravel_tex_primitive:nnn { letterspacefont } { letterspace_font } { 0 }
-\__unravel_tex_primitive:nnn { pdfcopyfont     } { pdf_copy_font } { 0 }
+\__unravel_tex_primitive_pdf:nnn { copyfont    } { pdf_copy_font } { 0 }
 \__unravel_tex_primitive:nnn { undefined         } { undefined_cs } { 0 }
 \__unravel_tex_primitive:nnn { ndefined          } { undefined_cs } { 0 }
 \__unravel_tex_primitive:nnn { expandafter       } { expand_after } { 0 }
 \__unravel_tex_primitive:nnn { unless            } { expand_after } { 1 }
-\__unravel_tex_primitive:nnn { pdfprimitive      } { no_expand } { 1 }
+\__unravel_tex_primitive_pdf:nnn { primitive     } { no_expand } { 1 }
 \__unravel_tex_primitive:nnn { noexpand          } { no_expand } { 0 }
 \__unravel_tex_primitive:nnn { input             } { input } { 0 }
 \__unravel_tex_primitive:nnn { endinput          } { input } { 1 }
@@ -1203,12 +1265,12 @@
 \__unravel_tex_primitive:nnn { ifdim             } { if_test } { 3 }
 \__unravel_tex_primitive:nnn { ifodd             } { if_test } { 4 }
 \__unravel_tex_primitive:nnn { ifvmode           } { if_test } { 5 }
-\__unravel_tex_primitive:nnn { ifhmode           } { if_test } { 6 }
-\__unravel_tex_primitive:nnn { ifmmode           } { if_test } { 7 }
-\__unravel_tex_primitive:nnn { ifinner           } { if_test } { 8 }
+\__unravel_tex_primitive:nnn { ifhmode           } { if_test } { 5 }
+\__unravel_tex_primitive:nnn { ifmmode           } { if_test } { 5 }
+\__unravel_tex_primitive:nnn { ifinner           } { if_test } { 5 }
 \__unravel_tex_primitive:nnn { ifvoid            } { if_test } { 9 }
-\__unravel_tex_primitive:nnn { ifhbox            } { if_test } { 10 }
-\__unravel_tex_primitive:nnn { ifvbox            } { if_test } { 11 }
+\__unravel_tex_primitive:nnn { ifhbox            } { if_test } { 9 }
+\__unravel_tex_primitive:nnn { ifvbox            } { if_test } { 9 }
 \__unravel_tex_primitive:nnn { ifx               } { if_test } { 12 }
 \__unravel_tex_primitive:nnn { ifeof             } { if_test } { 13 }
 \__unravel_tex_primitive:nnn { iftrue            } { if_test } { 14 }
@@ -1218,13 +1280,30 @@
 \__unravel_tex_primitive:nnn { ifcsname          } { if_test } { 18 }
 \__unravel_tex_primitive:nnn { iffontchar        } { if_test } { 19 }
 \__unravel_tex_primitive:nnn { ifincsname        } { if_test } { 20 }
+\__unravel_tex_primitive:nnn { ifprimitive       } { if_test } { 21 }
 \__unravel_tex_primitive:nnn { ifpdfprimitive    } { if_test } { 21 }
+\__unravel_tex_primitive:nnn { ifabsnum          } { if_test } { 22 }
 \__unravel_tex_primitive:nnn { ifpdfabsnum       } { if_test } { 22 }
+\__unravel_tex_primitive:nnn { ifabsdim          } { if_test } { 23 }
 \__unravel_tex_primitive:nnn { ifpdfabsdim       } { if_test } { 23 }
+\bool_if:nT { \sys_if_engine_ptex_p: || \sys_if_engine_uptex_p: }
+  {
+    \__unravel_tex_primitive:nnn { iftdir        } { if_test } { 5 }
+    \__unravel_tex_primitive:nnn { ifydir        } { if_test } { 5 }
+    \__unravel_tex_primitive:nnn { ifddir        } { if_test } { 5 }
+    \__unravel_tex_primitive:nnn { ifmdir        } { if_test } { 5 }
+    \__unravel_tex_primitive:nnn { iftbox        } { if_test } { 9 }
+    \__unravel_tex_primitive:nnn { ifybox        } { if_test } { 9 }
+    \__unravel_tex_primitive:nnn { ifdbox        } { if_test } { 9 }
+    \__unravel_tex_primitive:nnn { ifmbox        } { if_test } { 9 }
+    \__unravel_tex_primitive:nnn { ifjfont       } { if_test } { 24 }
+    \__unravel_tex_primitive:nnn { iftfont       } { if_test } { 24 }
+  }
 \__unravel_tex_primitive:nnn { fi                } { fi_or_else } { 2 }
 \__unravel_tex_primitive:nnn { else              } { fi_or_else } { 3 }
 \__unravel_tex_primitive:nnn { or                } { fi_or_else } { 4 }
 \__unravel_tex_primitive:nnn { csname            } { cs_name } { 0 }
+\__unravel_tex_primitive:nnn { lastnamedcs       } { cs_name } { 1 }
 \__unravel_tex_primitive:nnn { number            } { convert } { 0 }
 \__unravel_tex_primitive:nnn { romannumeral      } { convert } { 1 }
 \__unravel_tex_primitive:nnn { string            } { convert } { 2 }
@@ -1231,33 +1310,32 @@
 \__unravel_tex_primitive:nnn { meaning           } { convert } { 3 }
 \__unravel_tex_primitive:nnn { fontname          } { convert } { 4 }
 \__unravel_tex_primitive:nnn { eTeXrevision      } { convert } { 5 }
-\__unravel_tex_primitive:nnn { pdftexrevision    } { convert } { 6 }
-\__unravel_tex_primitive:nnn { pdftexbanner      } { convert } { 7 }
+\__unravel_tex_primitive_pdf:nnn { texrevision   } { convert } { 6 }
+\__unravel_tex_primitive_pdf:nnn { texbanner     } { convert } { 7 }
 \__unravel_tex_primitive:nnn { pdffontname       } { convert } { 8 }
-\__unravel_tex_primitive:nnn { pdffontobjnum     } { convert } { 9 }
-\__unravel_tex_primitive:nnn { pdffontsize       } { convert } { 10 }
-\__unravel_tex_primitive:nnn { pdfpageref        } { convert } { 11 }
-\__unravel_tex_primitive:nnn { pdfxformname      } { convert } { 12 }
-\__unravel_tex_primitive:nnn { pdfescapestring   } { convert } { 13 }
-\__unravel_tex_primitive:nnn { pdfescapename     } { convert } { 14 }
+\__unravel_tex_primitive_pdf:nnn { fontobjnum    } { convert } { 9 }
+\__unravel_tex_primitive_pdf:nnn { fontsize      } { convert } { 10 }
+\__unravel_tex_primitive_pdf:nnn { pageref       } { convert } { 11 }
+\__unravel_tex_primitive_pdf:nnn { xformname     } { convert } { 12 }
+\__unravel_tex_primitive_pdf:nnn { escapestring  } { convert } { 13 }
+\__unravel_tex_primitive_pdf:nnn { escapename    } { convert } { 14 }
 \__unravel_tex_primitive:nnn { leftmarginkern    } { convert } { 15 }
 \__unravel_tex_primitive:nnn { rightmarginkern   } { convert } { 16 }
-\__unravel_tex_primitive:nnn
-  { \sys_if_engine_xetex:F { pdf } strcmp } { convert } { 17 }
-\__unravel_tex_primitive:nnn { pdfcolorstackinit } { convert } { 18 }
-\__unravel_tex_primitive:nnn { pdfescapehex      } { convert } { 19 }
-\__unravel_tex_primitive:nnn { pdfunescapehex    } { convert } { 20 }
-\__unravel_tex_primitive:nnn { pdfcreationdate   } { convert } { 21 }
-\__unravel_tex_primitive:nnn { pdffilemoddate    } { convert } { 22 }
-\__unravel_tex_primitive:nnn { pdffilesize       } { convert } { 23 }
-\__unravel_tex_primitive:nnn { pdfmdfivesum      } { convert } { 24 }
-\__unravel_tex_primitive:nnn { pdffiledump       } { convert } { 25 }
-\__unravel_tex_primitive:nnn { pdfmatch          } { convert } { 26 }
-\__unravel_tex_primitive:nnn { pdflastmatch      } { convert } { 27 }
-\__unravel_tex_primitive:nnn { pdfuniformdeviate } { convert } { 28 }
-\__unravel_tex_primitive:nnn { pdfnormaldeviate  } { convert } { 29 }
-\__unravel_tex_primitive:nnn { pdfinsertht       } { convert } { 30 }
-\__unravel_tex_primitive:nnn { pdfximagebbox     } { convert } { 31 }
+\__unravel_tex_primitive_pdf:nnn { strcmp        } { convert } { 17 }
+\__unravel_tex_primitive_pdf:nnn { colorstackinit } { convert } { 18 }
+\__unravel_tex_primitive_pdf:nnn { escapehex     } { convert } { 19 }
+\__unravel_tex_primitive_pdf:nnn { unescapehex   } { convert } { 20 }
+\__unravel_tex_primitive_pdf:nnn { creationdate  } { convert } { 21 }
+\__unravel_tex_primitive_pdf:nnn { filemoddate   } { convert } { 22 }
+\__unravel_tex_primitive_pdf:nnn { filesize      } { convert } { 23 }
+\__unravel_tex_primitive_pdf:nnn { mdfivesum     } { convert } { 24 }
+\__unravel_tex_primitive_pdf:nnn { filedump      } { convert } { 25 }
+\__unravel_tex_primitive_pdf:nnn { match         } { convert } { 26 }
+\__unravel_tex_primitive_pdf:nnn { lastmatch     } { convert } { 27 }
+\__unravel_tex_primitive_pdf:nnn { uniformdeviate } { convert } { 28 }
+\__unravel_tex_primitive_pdf:nnn { normaldeviate } { convert } { 29 }
+\__unravel_tex_primitive_pdf:nnn { insertht      } { convert } { 30 }
+\__unravel_tex_primitive_pdf:nnn { ximagebbox    } { convert } { 31 }
 \__unravel_tex_primitive:nnn { jobname           } { convert } { 32 }
 \sys_if_engine_luatex:T
   { \__unravel_tex_primitive:nnn { directlua     } { convert } { 33 } }
@@ -1426,13 +1504,30 @@
     \int_set:Nn \l__unravel_head_cmd_int { \__unravel_tex_use:n { call } }
     \int_zero:N \l__unravel_head_char_int
   }
-\cs_new_protected:Npn \__unravel_set_cmd_aux_unknown:
+\sys_if_engine_luatex:TF
   {
-    \exp_last_unbraced:NV \__unravel_set_cmd_aux_primitive:nn
-      \c__unravel_tex_relax_tl
-    \__unravel_error:nxxxx { unknown-primitive }
-      { \l__unravel_head_meaning_tl } { } { } { }
+    \cs_new_protected:Npn \__unravel_set_cmd_aux_unknown:
+      {
+        \exp_last_unbraced:NV \__unravel_set_cmd_aux_primitive:nn
+          \c__unravel_tex_relax_tl
+        \__unravel_tl_if_in:ooTF \l__unravel_head_meaning_tl
+          { \tl_to_str:n { xpandable~luacall } }
+          { }
+          {
+            \__unravel_error:nxxxx { unknown-primitive }
+              { \l__unravel_head_meaning_tl } { } { } { }
+          }
+      }
   }
+  {
+    \cs_new_protected:Npn \__unravel_set_cmd_aux_unknown:
+      {
+        \exp_last_unbraced:NV \__unravel_set_cmd_aux_primitive:nn
+          \c__unravel_tex_relax_tl
+        \__unravel_error:nxxxx { unknown-primitive }
+          { \l__unravel_head_meaning_tl } { } { } { }
+      }
+  }
 \cs_new_protected:Npn \__unravel_set_cmd_aux_cs:
   {
     \__unravel_tl_if_in:ooTF \l__unravel_head_meaning_tl
@@ -1820,8 +1915,7 @@
           { \__unravel_error:nxxxx { internal } { expandable } { } { } { } }
       }
       {
-        \__unravel_error:nxxxx { unknown-primitive }
-          { \l__unravel_head_meaning_tl } { } { } { }
+        \__unravel_set_cmd_aux_unknown:
         \__unravel_input_gpop_tl:N \l__unravel_tmpa_tl
         \tl_put_right:NV \l__unravel_head_tl \l__unravel_tmpa_tl
         \exp_args:NV \__unravel_back_input:o \l__unravel_head_tl
@@ -2006,7 +2100,7 @@
     \__unravel_scan_int:
     \__unravel_scan_font_ident:
   }
-\cs_new_protected:Npn \__unravel_scan_something_internal:n #1
+\cs_new_protected:Npn \__unravel_rescan_something_internal:n #1
   {
     \__unravel_set_cmd:
     \__unravel_set_action_text:
@@ -2021,13 +2115,13 @@
         \__unravel_back_input:
         \__unravel_tex_error:nV { missing-number } \l__unravel_head_tl
         \__unravel_thing_use_get:nnNN { 1 } {#3} \c_zero_dim \l__unravel_tmpa_tl
-        \__unravel_scan_something_internal_auxii:Vn \l__unravel_tmpa_tl { 1 }
+        \__unravel_rescan_something_internal_auxii:Vn \l__unravel_tmpa_tl { 1 }
         \__unravel_break:w
       }
     \int_compare:nNnT {#1} = { 8 }
       {
         \__unravel_tex_error:nV { the-cannot } \l__unravel_head_tl
-        \__unravel_scan_something_internal_auxii:nn 0 { 0 }
+        \__unravel_rescan_something_internal_auxii:nn 0 { 0 }
         \__unravel_break:w
       }
     \tl_if_empty:nF {#2}
@@ -2040,11 +2134,11 @@
     \int_compare:nNnTF {#3} < { 4 }
       { \__unravel_thing_use_get:nnNN {#1} {#3} \l__unravel_head_tl \l__unravel_tmpa_tl }
       { \tl_set:Nx \l__unravel_tmpa_tl { \__unravel_the:w \l__unravel_head_tl } }
-    \__unravel_scan_something_internal_auxii:Vn \l__unravel_tmpa_tl {#1}
+    \__unravel_rescan_something_internal_auxii:Vn \l__unravel_tmpa_tl {#1}
     \__unravel_break_point:
     \int_compare:nNnT {#3} < { 4 } { \__unravel_print_action: }
   }
-\cs_new_protected:Npn \__unravel_scan_something_internal_auxii:nn #1#2
+\cs_new_protected:Npn \__unravel_rescan_something_internal_auxii:nn #1#2
   {
     \__unravel_prev_input_silent:n {#1}
     \__unravel_set_action_text:
@@ -2052,7 +2146,7 @@
       { \g__unravel_action_text_str \use:n { ~ => ~ } \tl_to_str:n {#1} }
     \int_gset:Nn \g__unravel_val_level_int {#2}
   }
-\cs_generate_variant:Nn \__unravel_scan_something_internal_auxii:nn { V }
+\cs_generate_variant:Nn \__unravel_rescan_something_internal_auxii:nn { V }
 \cs_new:Npn \__unravel_thing_case:
   {
     \int_case:nnF \l__unravel_head_cmd_int
@@ -2259,7 +2353,7 @@
     \__unravel_scan_signs:
     \__unravel_set_cmd:
     \__unravel_cmd_if_internal:TF
-      { \__unravel_scan_something_internal:n { 0 } }
+      { \__unravel_rescan_something_internal:n { 0 } }
       { \__unravel_scan_int_char: }
   }
 \cs_new_protected:Npn \__unravel_scan_int_char:
@@ -2330,8 +2424,8 @@
     \__unravel_cmd_if_internal:TF
       {
         \int_compare:nNnTF {#1} = { 3 }
-          { \__unravel_scan_something_internal:n { 3 } }
-          { \__unravel_scan_something_internal:n { 1 } }
+          { \__unravel_rescan_something_internal:n { 3 } }
+          { \__unravel_rescan_something_internal:n { 1 } }
         \int_compare:nNnT \g__unravel_val_level_int = { 0 }
           { \__unravel_scan_dim_unit:nN {#1} #2 }
       }
@@ -2384,7 +2478,7 @@
     \__unravel_cmd_if_internal:TF
       {
         \__unravel_prev_input_gpush:
-        \__unravel_scan_something_internal:n {#1}
+        \__unravel_rescan_something_internal:n {#1}
         \int_compare:nNnTF \g__unravel_val_level_int = { 0 }
           { \__unravel_prev_input_join_get:nnN {#1} { sp } \l__unravel_tmpa_tl }
           { \__unravel_prev_input_join_get:nnN {#1} { } \l__unravel_tmpa_tl }
@@ -2451,7 +2545,7 @@
     \__unravel_set_cmd:
     \__unravel_cmd_if_internal:TF
       {
-        \__unravel_scan_something_internal:n {#1}
+        \__unravel_rescan_something_internal:n {#1}
         \int_case:nnF \g__unravel_val_level_int
           {
             { 0 } { \__unravel_scan_dim_unit:nN {#1} \c_false_bool }
@@ -2473,11 +2567,18 @@
   }
 \cs_new_protected:Npn \__unravel_scan_file_name:
   {
-    \bool_gset_true:N \g__unravel_name_in_progress_bool
-    \__unravel_get_x_non_blank:
-    \__unravel_scan_file_name_loop:
-    \bool_gset_false:N \g__unravel_name_in_progress_bool
-    \__unravel_prev_input_silent:n { ~ }
+    \__unravel_get_x_non_relax:
+    \token_if_eq_catcode:NNTF \l__unravel_head_token \c_group_begin_token
+      { \__unravel_scan_group_x:N \c_false_bool }
+      {
+        \__unravel_back_input:
+        \bool_gset_true:N \g__unravel_name_in_progress_bool
+        \bool_gset_false:N \g__unravel_quotes_bool
+        \__unravel_get_x_non_blank:
+        \__unravel_scan_file_name_loop:
+        \bool_gset_false:N \g__unravel_name_in_progress_bool
+        \__unravel_prev_input_silent:n { ~ }
+      }
   }
 \cs_new_protected:Npn \__unravel_scan_file_name_loop:
   {
@@ -2486,8 +2587,14 @@
       {
         \tl_set:Nx \l__unravel_tmpa_tl
           { \__unravel_token_to_char:N \l__unravel_head_token }
-        \tl_if_eq:NNF \l__unravel_tmpa_tl \c_space_tl
+        \tl_if_eq:NNT \l__unravel_tmpa_tl \c__unravel_dq_tl
           {
+            \bool_if:NTF \g__unravel_quotes_bool
+              { \bool_set_false:N } { \bool_set_true:N } \g__unravel_quotes_bool
+          }
+        \bool_if:NTF \g__unravel_quotes_bool
+          { \use:n } { \tl_if_eq:NNF \l__unravel_tmpa_tl \c_space_tl }
+          {
             \__unravel_prev_input_silent:V \l__unravel_tmpa_tl
             \__unravel_get_x_next:
             \__unravel_scan_file_name_loop:
@@ -2494,6 +2601,7 @@
           }
       }
   }
+\bool_new:N \g__unravel_quotes_bool
 \cs_new_protected:Npn \__unravel_scan_r_token:
   {
     \bool_do_while:nn
@@ -2734,7 +2842,6 @@
     \token_if_eq_meaning:NNTF \l__unravel_head_token \__unravel_hbox:w
       { \__unravel_box_hook:N \tex_everyhbox:D }
       { \__unravel_box_hook:N \tex_everyvbox:D }
-      % ^^A todo: TeX calls |normal_paragraph| here.
     \__unravel_scan_spec:
     \__unravel_prev_input_gpop:N \l__unravel_head_tl
     \__unravel_set_action_text:x
@@ -2795,13 +2902,18 @@
   {
     \tex_char:D #1 \scan_stop:
     \__unravel_charcode_if_safe:nTF {#1}
-      { \tl_set:Nx \l__unravel_tmpa_tl { \char_generate:nn {#1} { 12 } } }
       {
+        \tl_set:Nx \l__unravel_tmpa_tl { \char_generate:nn {#1} { 12 } }
+        \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_tmpa_tl
+        \__unravel_print_action:x { \tl_to_str:N \l__unravel_tmpa_tl }
+      }
+      {
         \tl_set:Nx \l__unravel_tmpa_tl
           { \exp_not:N \char \int_eval:n {#1} ~ }
+        \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_tmpa_tl
+        \__unravel_print_action:x
+          { " \char_generate:nn {#1} { 12 } " = \tl_to_str:N \l__unravel_tmpa_tl }
       }
-    \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_tmpa_tl
-    \__unravel_print_action:x { \tl_to_str:N \l__unravel_tmpa_tl }
   }
 \cs_generate_variant:Nn \__unravel_char:n { V }
 \cs_new_protected:Npn \__unravel_char:x
@@ -2808,11 +2920,13 @@
   { \__unravel_exp_args:Nx \__unravel_char:n }
 \cs_new_protected:Npn \__unravel_char_in_mmode:n #1
   {
-    \int_compare:nNnTF { \tex_mathcode:D #1 } = { "8000 }
+    \int_compare:nNnTF { \tex_mathcode:D #1 }
+      = { \sys_if_engine_luatex:TF { "1000000 } { "8000 } }
       { % math active
-        \__unravel_exp_args:NNx \gtl_set:Nn \l__unravel_head_gtl
-          { \char_generate:nn {#1} { 12 } }
+        \__unravel_active_do:nn {#1} { \gtl_set:Nn \l__unravel_head_gtl }
         \__unravel_back_input:
+        \__unravel_print_action:x
+          { \char_generate:nn {#1} { 12 } ~ active }
       }
       { \__unravel_char:n {#1} }
   }
@@ -2823,7 +2937,7 @@
   {
     \tex_mathchar:D #1 \scan_stop:
     \tl_set:Nx \l__unravel_tmpa_tl
-      { \exp_not:N \mathchar \int_eval:n {#1} ~ }
+      { \exp_not:N \mathchar " \int_to_hex:n {#1} ~ }
     \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_tmpa_tl
     \__unravel_print_action:x { \tl_to_str:N \l__unravel_tmpa_tl }
   }
@@ -2842,9 +2956,9 @@
         \token_to_str:N \everypar = { \tl_to_str:N \l__unravel_tmpa_tl }
       }
   }
-\cs_new_protected:Npn \__unravel_end_graf:
-  { \mode_if_horizontal:T { \__unravel_normal_paragraph: } }
-\cs_new_protected:Npn \__unravel_normal_paragraph:
+\cs_new_protected:Npn \__unravel_par_if_hmode:
+  { \mode_if_horizontal:T { \__unravel_par: } }
+\cs_new_protected:Npn \__unravel_par:
   {
     \tex_par:D
     \gtl_gput_right:Nn \g__unravel_output_gtl { \par }
@@ -2853,6 +2967,7 @@
 \cs_new_protected:Npn \__unravel_build_page:
   {
   }
+\int_new:N \l__unravel_choice_int
 \cs_new_protected:Npn \__unravel_handle_right_brace:
   {
     \int_compare:nTF { 1 <= \__unravel_currentgrouptype: <= 13 }
@@ -2859,22 +2974,27 @@
       {
         \gtl_gconcat:NNN \g__unravel_output_gtl
           \g__unravel_output_gtl \c_group_end_gtl
-        \__unravel_back_input_gtl:N \l__unravel_after_group_gtl
+        \int_case:nnF \__unravel_currentgrouptype:
+          {
+            { 10 } { } % disc
+            { 13 } { } % math_choice
+          }
+          { \__unravel_back_input_gtl:N \l__unravel_after_group_gtl }
         \int_case:nn \__unravel_currentgrouptype:
           {
             { 1 } { \__unravel_end_simple_group: } % simple
             { 2 } { \__unravel_end_box_group: } % hbox
             { 3 } { \__unravel_end_box_group: } % adjusted_hbox
-            { 4 } { \__unravel_end_graf: \__unravel_end_box_group: } % vbox
-            { 5 } { \__unravel_end_graf: \__unravel_end_box_group: } % vtop
+            { 4 } { \__unravel_par_if_hmode: \__unravel_end_box_group: } % vbox
+            { 5 } { \__unravel_par_if_hmode: \__unravel_end_box_group: } % vtop
             { 6 } { \__unravel_end_align_group: } % align
             { 7 } { \__unravel_end_no_align_group: } % no_align
             { 8 } { \__unravel_end_output_group: } % output
             { 9 } { \__unravel_end_simple_group: } % math
-            { 10 } { \__unravel_end_disc_group: } % disc
-            { 11 } { \__unravel_end_graf: \__unravel_end_simple_group: } % insert
-            { 12 } { \__unravel_end_graf: \__unravel_end_simple_group: } % vcenter
-            { 13 } { \__unravel_end_math_choice_group: } % math_choice
+            { 10 } { \__unravel_end_choice_group:NN 2 \discretionary  } % disc
+            { 11 } { \__unravel_par_if_hmode: \__unravel_end_simple_group: } % insert
+            { 12 } { \__unravel_par_if_hmode: \__unravel_end_simple_group: } % vcenter
+            { 13 } { \__unravel_end_choice_group:NN 3 \mathchoice } % math_choice
           }
       }
       { % bottom_level, semi_simple, math_shift, math_left
@@ -2912,6 +3032,49 @@
           }
       }
   }
+\cs_new_protected:Npn \__unravel_end_align_group:
+  {
+    \__unravel_not_implemented:n { end_align_group }
+    \__unravel_end_simple_group:
+  }
+\cs_new_protected:Npn \__unravel_end_no_align_group:
+  {
+    \__unravel_not_implemented:n { end_no_align_group }
+    \__unravel_end_simple_group:
+  }
+\cs_new_protected:Npn \__unravel_end_output_group:
+  {
+    \__unravel_not_implemented:n { end_output_group }
+    \__unravel_end_simple_group:
+  }
+\cs_new_protected:Npn \__unravel_end_choice_group:NN #1#2
+  {
+    \int_compare:nNnTF \l__unravel_choice_int > {#1}
+      {
+        \__unravel_back_input_gtl:N \l__unravel_after_group_gtl
+        \c_group_end_token
+        \__unravel_print_action:x
+          { \token_to_str:N #2 \prg_replicate:nn { #1 + 1 } { {...} } }
+      }
+      { \exp_args:NV \__unravel_end_choice_group:nN \l__unravel_choice_int #2 }
+  }
+\cs_new_protected:Npn \__unravel_end_choice_group:nN #1#2
+  {
+    \__unravel_scan_left_brace:
+    \gtl_gconcat:NNN \g__unravel_output_gtl
+      \g__unravel_output_gtl \c_group_begin_gtl
+    \__unravel_back_input_gtl:N \l__unravel_after_group_gtl
+    \use:n \c_group_end_token
+    \use:n \c_group_begin_token
+    \int_set:Nn \l__unravel_choice_int { #1 + 1 }
+    \gtl_clear:N \l__unravel_after_group_gtl
+    \__unravel_print_action:x
+      {
+        \token_to_str:N #2
+        \prg_replicate:nn {#1} { { ... } }
+        \iow_char:N \{
+      }
+  }
 \cs_new_protected:Npn \__unravel_off_save:
   {
     \int_compare:nNnTF \__unravel_currentgrouptype: = { 0 }
@@ -2984,13 +3147,10 @@
 \cs_new_protected:Npn \__unravel_after_math:
   {
     \mode_if_inner:TF
+      { \int_compare:nNnTF \l__unravel_choice_int > 0 }
+      { \use_i:nn }
       {
         \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
-        \__unravel_back_input_gtl:N \l__unravel_after_group_gtl
-        $ % $
-      }
-      {
-        \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
         \__unravel_get_x_next:
         \token_if_eq_catcode:NNF
           \l__unravel_head_token \c_math_toggle_token
@@ -3003,6 +3163,11 @@
         \__unravel_back_input_gtl:N \l__unravel_after_group_gtl
         $ $
       }
+      {
+        \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
+        \__unravel_back_input_gtl:N \l__unravel_after_group_gtl
+        $ % $
+      }
     \__unravel_print_action:
   }
 \cs_new_protected:Npn \__unravel_forbidden_case:
@@ -3073,6 +3238,10 @@
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
+    \__unravel_do_one_atom:
+  }
+\cs_new_protected:Npn \__unravel_do_one_atom:
+  {
     \__unravel_get_x_non_relax:
     \__unravel_set_cmd:
     \int_case:nnTF \l__unravel_head_cmd_int
@@ -3115,7 +3284,12 @@
     \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
   }
 \__unravel_new_tex_cmd:nn { endv }                                 % 9
-  { \__unravel_not_implemented:n { alignments } }
+  {
+    \__unravel_mode_non_math:n
+      {
+        \__unravel_not_implemented:n { alignments }
+      }
+  }
 \__unravel_new_tex_cmd:nn { blank_char }                           % 10
   {
     \mode_if_horizontal:T
@@ -3142,10 +3316,10 @@
     \__unravel_mode_non_math:n
       {
         \mode_if_vertical:TF
-          { \__unravel_normal_paragraph: }
+          { \__unravel_par: }
           {
             % if align_state<0 then off_save;
-            \__unravel_end_graf:
+            \__unravel_par_if_hmode:
             \mode_if_vertical:T
               { \mode_if_inner:F { \__unravel_build_page: } }
           }
@@ -3252,7 +3426,7 @@
         { 2 }
           { % showthe
             \__unravel_get_x_next:
-            \__unravel_scan_something_internal:n { 5 }
+            \__unravel_rescan_something_internal:n { 5 }
             \__unravel_prev_input_gpop:N \l__unravel_head_tl
             \__unravel_exp_args:Nx \use:n
               { \tex_showtokens:D { \tl_tail:N \l__unravel_head_tl } }
@@ -3351,7 +3525,9 @@
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
-    \__unravel_do_box:N \c_true_bool
+    \tl_if_head_eq_meaning:VNTF \l__unravel_head_tl \tex_shipout:D
+      { \__unravel_do_box:N \c_false_bool }
+      { \__unravel_do_box:N \c_true_bool }
   }
 \__unravel_new_tex_cmd:nn { halign }                               % 32
   { \__unravel_not_implemented:n { halign } }
@@ -3358,7 +3534,7 @@
 \__unravel_new_tex_cmd:nn { valign }                               % 33
   { \__unravel_not_implemented:n { valign } }
 \__unravel_new_tex_cmd:nn { no_align }                             % 34
-  { \__unravel_not_implemented:n { noalign } }
+  { \l__unravel_head_token \__unravel_print_action: }
 \__unravel_new_tex_cmd:nn { vrule }                                % 35
   { \__unravel_mode_non_vertical:n { \__unravel_do_rule: } }
 \__unravel_new_tex_cmd:nn { hrule }                                % 36
@@ -3373,12 +3549,34 @@
     \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
   }
 \__unravel_new_tex_cmd:nn { insert }                               % 37
-  { \__unravel_begin_insert_or_adjust: }
+  {
+    \__unravel_prev_input_gpush:N \l__unravel_head_tl
+    \__unravel_print_action:
+    \__unravel_scan_int:
+    \__unravel_begin_insert_or_adjust:
+  }
 \__unravel_new_tex_cmd:nn { vadjust }                              % 38
   {
     \mode_if_vertical:TF
-      { \__unravel_forbidden_case: } { \__unravel_begin_insert_or_adjust: }
+      { \__unravel_forbidden_case: }
+      {
+        \__unravel_prev_input_gpush:N \l__unravel_head_tl
+        \__unravel_print_action:
+        \__unravel_scan_keyword:nTF { pPrReE }
+        \__unravel_begin_insert_or_adjust:
+      }
   }
+\cs_new_protected:Npn \__unravel_begin_insert_or_adjust:
+  {
+    \__unravel_scan_left_brace:
+    \__unravel_prev_input_gpop:N \l__unravel_head_tl
+    \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
+    \gtl_gconcat:NNN \g__unravel_output_gtl
+      \g__unravel_output_gtl \c_group_begin_gtl
+    \tl_use:N \l__unravel_head_tl \c_group_begin_token
+    \__unravel_print_action:x
+      { \tl_to_str:N \l__unravel_head_tl \iow_char:N \{ }
+  }
 \__unravel_new_tex_cmd:nn { ignore_spaces }                        % 39
   {
     \token_if_eq_meaning:NNTF \l__unravel_head_token \tex_ignorespaces:D
@@ -3492,11 +3690,7 @@
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
     \__unravel_scan_int:
-    \__unravel_scan_math:
-    \__unravel_prev_input_gpop:N \l__unravel_head_tl
-    \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
-    \tl_use:N \l__unravel_head_tl \scan_stop:
-    \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
+    \__unravel_do_one_atom:
   }
 \__unravel_new_tex_cmd:nn { accent }                               % 45
   {
@@ -3509,25 +3703,129 @@
 \__unravel_new_tex_cmd:nn { math_accent }                          % 46
   { \__unravel_mode_math:n { \__unravel_do_math_accent: } }
 \__unravel_new_tex_cmd:nn { discretionary }                        % 47
-  { \__unravel_not_implemented:n { discretionary } }
+  {
+    \__unravel_mode_non_vertical:n
+      {
+        \int_compare:nNnTF \l__unravel_head_char_int = { 1 }
+          { \__unravel_output_head_token: }
+          { \__unravel_do_choice: }
+      }
+  }
 \__unravel_new_tex_cmd:nn { eq_no }                                % 48
-  { \__unravel_not_implemented:n { eqno } }
+  {
+    \mode_if_math:TF
+      {
+        \mode_if_inner:TF
+          { \__unravel_off_save: }
+          {
+            \int_compare:nNnTF \tex_currentgrouptype:D = { 15 }
+              {
+                \__unravel_box_hook:N \tex_everymath:D
+                \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
+                \l__unravel_head_token
+                \__unravel_box_hook_end:
+                \int_set:Nn \l__unravel_choice_int { 1 }
+              }
+              { \__unravel_off_save: }
+          }
+      }
+      { \__unravel_forbidden_case: }
+  }
 \__unravel_new_tex_cmd:nn { left_right }                           % 49
-  { \__unravel_not_implemented:n { left/right } }
+  {
+    \__unravel_mode_math:n
+      {
+        \__unravel_prev_input_gpush:N \l__unravel_head_tl
+        \__unravel_print_action:
+        \__unravel_scan_delimiter:
+        \__unravel_prev_input_gpop:N \l__unravel_head_tl
+        \tl_if_head_eq_meaning:nNTF \l__unravel_head_tl \tex_left:D
+          {
+            \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
+            \tl_use:N \l__unravel_head_tl \scan_stop:
+            \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
+          }
+          {
+            \int_case:nnF \tex_currentgrouptype:D
+              {
+                { 16 }
+                  {
+                    \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
+                    \__unravel_back_input_gtl:N \l__unravel_after_group_gtl
+                    \tl_if_head_eq_meaning:nNTF \l__unravel_head_tl \tex_middle:D
+                      {
+                        \tl_use:N \l__unravel_head_tl \scan_stop:
+                        \gtl_clear:N \l__unravel_after_group_gtl
+                      }
+                      { \tl_use:N \l__unravel_head_tl \scan_stop: }
+                    \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
+                  }
+                { 15 }
+                  { % todo: this is a TeX error
+                    \tl_use:N \l__unravel_head_tl \scan_stop:
+                  }
+              }
+              { \__unravel_off_save: }
+          }
+      }
+  }
+\cs_new_protected:Npn \__unravel_scan_delimiter:
+  {
+    \__unravel_get_x_non_relax:
+    \__unravel_set_cmd:
+    \int_case:nnF \l__unravel_head_cmd_int
+      {
+        { \__unravel_tex_use:n { the_char } }
+          { \__unravel_prev_input:V \l__unravel_head_tl }
+        { \__unravel_tex_use:n { other_char } }
+          { \__unravel_prev_input:V \l__unravel_head_tl }
+        { \__unravel_tex_use:n { delim_num } }
+          {
+            \__unravel_prev_input:V \l__unravel_head_tl
+            \__unravel_scan_int:
+          }
+      }
+      {
+        \__unravel_back_input:
+        \__unravel_tex_error:nV { missing-delim } \l__unravel_head_tl
+        \__unravel_prev_input:n { . }
+      }
+  }
 \__unravel_new_tex_cmd:nn { math_comp }                            % 50
-  { \__unravel_not_implemented:n { math~comp } }
+  { \__unravel_mode_math:n { \__unravel_sub_sup: } }
 \__unravel_new_tex_cmd:nn { limit_switch }                         % 51
-  { \__unravel_not_implemented:n { limits } }
+  { \__unravel_mode_math:n { \__unravel_output_head_token: } }
+\cs_new_protected:Npn \__unravel_output_head_token:
+  {
+    \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
+    \l__unravel_head_token
+    \__unravel_print_action:
+  }
 \__unravel_new_tex_cmd:nn { above }                                % 52
-  { \__unravel_not_implemented:n { above } }
+  { \__unravel_mode_math:n { \__unravel_not_implemented:n { above } } }
 \__unravel_new_tex_cmd:nn { math_style }                           % 53
-  { \__unravel_not_implemented:n { math~style } }
+  { \__unravel_mode_math:n { \__unravel_output_head_token: } }
 \__unravel_new_tex_cmd:nn { math_choice }                          % 54
-  { \__unravel_not_implemented:n { math~choice } }
+  { \__unravel_mode_math:n { \__unravel_do_choice: } }
+\cs_new_protected:Npn \__unravel_do_choice:
+  {
+    \__unravel_prev_input_gpush:N \l__unravel_head_tl
+    \__unravel_print_action:
+    \__unravel_scan_left_brace:
+    \__unravel_prev_input_gpop:N \l__unravel_head_tl
+    \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
+    \gtl_gconcat:NNN \g__unravel_output_gtl
+      \g__unravel_output_gtl \c_group_begin_gtl
+    \tl_use:N \l__unravel_head_tl \c_group_begin_token
+    \gtl_clear:N \l__unravel_after_group_gtl
+    \int_set:Nn \l__unravel_choice_int { 1 }
+    \__unravel_print_action:x
+      { \tl_to_str:N \l__unravel_head_tl \iow_char:N \{ }
+  }
 \__unravel_new_tex_cmd:nn { non_script }                           % 55
-  { \__unravel_not_implemented:n { non~script } }
+  { \__unravel_mode_math:n { \__unravel_output_head_token: } }
 \__unravel_new_tex_cmd:nn { vcenter }                              % 56
-  { \__unravel_not_implemented:n { vcenter } }
+  { \__unravel_mode_math:n { \__unravel_not_implemented:n { vcenter } } }
 \__unravel_new_tex_cmd:nn { case_shift }                           % 57
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
@@ -3589,7 +3887,7 @@
     \__unravel_print_action:
   }
 \__unravel_new_tex_cmd:nn { omit }                                 % 63
-  { \__unravel_not_implemented:n { omit } }
+  { \l__unravel_head_token \__unravel_print_action: }
 \__unravel_new_tex_cmd:nn { ex_space }                             % 64
   {
     \__unravel_mode_non_vertical:n
@@ -3601,19 +3899,7 @@
       { \l__unravel_head_token \__unravel_print_action: }
   }
 \__unravel_new_tex_cmd:nn { radical }                              % 66
-  {
-    \__unravel_mode_math:n
-      {
-        \__unravel_prev_input_gpush:N \l__unravel_head_tl
-        \__unravel_print_action:
-        \__unravel_scan_int:
-        \__unravel_scan_math:
-        \__unravel_prev_input_gpop:N \l__unravel_head_tl
-        \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
-        \tl_use:N \l__unravel_head_tl \scan_stop:
-        \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
-      }
-  }
+  { \__unravel_mode_math:n { \__unravel_do_math_accent: } }
 \__unravel_new_tex_cmd:nn { end_cs_name }                          % 67
   {
     \__unravel_tex_error:nV { extra-endcsname } \l__unravel_head_tl
@@ -3895,7 +4181,11 @@
             \int_case:nnF \l__unravel_head_char_int
               {
                 { 7 } { \__unravel_scan_extension_operands_aux: } % pdfobj
-                { 9 } { \__unravel_scan_extension_operands_aux: } % pdfxform
+                { 9 }
+                  {
+                    \__unravel_prepare_mag:
+                    \__unravel_scan_extension_operands_aux:
+                  } % pdfxform
                 { 11 } { \__unravel_scan_extension_operands_aux: } %pdfximage
               }
               { \__unravel_scan_immediate_operands_bad: }
@@ -4216,6 +4506,7 @@
     \__unravel_print_action:x
       { \l__unravel_prev_action_tl \tl_to_str:N \l__unravel_defined_tl }
     \exp_after:wN \cs_set_eq:NN \l__unravel_defined_tl \scan_stop:
+    \__unravel_just_print_assigned_token:
     \__unravel_scan_optional_equals:
     \__unravel_scan_int:
     \__unravel_assign_token:n { }
@@ -4313,6 +4604,7 @@
     \__unravel_print_action:x
       { \g__unravel_action_text_str \tl_to_str:N \l__unravel_defined_tl }
     \exp_after:wN \cs_set_eq:NN \l__unravel_defined_tl \__unravel_nullfont:
+    \__unravel_just_print_assigned_token:
     \__unravel_scan_optional_equals:
     \__unravel_scan_font_ident:
     \__unravel_scan_int:
@@ -4326,6 +4618,7 @@
     \__unravel_print_action:x
       { \g__unravel_action_text_str \tl_to_str:N \l__unravel_defined_tl }
     \exp_after:wN \cs_set_eq:NN \l__unravel_defined_tl \__unravel_nullfont:
+    \__unravel_just_print_assigned_token:
     \__unravel_scan_optional_equals:
     \__unravel_scan_font_ident:
     \__unravel_assign_token:n { }
@@ -4456,7 +4749,7 @@
     \__unravel_token_if_expandable:NTF \l__unravel_head_token
       { \__unravel_expand_do:N \prg_do_nothing: }
       { \__unravel_back_input: }
-    \__unravel_prev_input_gpop:N \l__unravel_head_gtl
+    \__unravel_prev_input_gpop_gtl:N \l__unravel_head_gtl
     \__unravel_set_action_text:x
       { back_input: ~ \gtl_to_str:N \l__unravel_head_gtl }
     \gtl_pop_left:N \l__unravel_head_gtl
@@ -4566,12 +4859,21 @@
   }
 \__unravel_new_tex_expandable:nn { cs_name }                       % 109
   {
-    \__unravel_prev_input_gpush:N \l__unravel_head_tl
-    \__unravel_print_expansion:
-    \__unravel_csname_loop:
-    \__unravel_prev_input_silent:V \l__unravel_head_tl
-    \__unravel_prev_input_gpop:N \l__unravel_head_tl
-    \__unravel_back_input_tl_o:
+    \int_compare:nNnTF \l__unravel_head_char_int = 0
+      {
+        \__unravel_prev_input_gpush:N \l__unravel_head_tl
+        \__unravel_print_expansion:
+        \__unravel_csname_loop:
+        \__unravel_prev_input_silent:V \l__unravel_head_tl
+        \__unravel_get_lastnamedcs:
+        \__unravel_prev_input_gpop:N \l__unravel_head_tl
+        \__unravel_back_input_tl_o:
+      }
+      {
+        \__unravel_back_input:V \g__unravel_lastnamedcs_tl
+        \__unravel_print_expansion:x
+          { \tl_to_str:N \l__unravel_head_tl = \tl_to_str:N \g__unravel_lastnamedcs_tl }
+      }
   }
 \cs_new_protected:Npn \__unravel_csname_loop:
   {
@@ -4591,6 +4893,14 @@
         \__unravel_csname_loop:
       }
   }
+\cs_new_protected:Npn \__unravel_get_lastnamedcs:
+  {
+    \group_begin:
+    \__unravel_prev_input_get:N \l__unravel_head_tl
+    \tl_gset:No \g__unravel_lastnamedcs_tl
+      { \cs:w \exp_after:wN \use_none:n \l__unravel_head_tl }
+    \group_end:
+  }
 \__unravel_new_tex_expandable:nn { convert }                       % 110
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
@@ -4600,7 +4910,7 @@
         0      \__unravel_scan_int:
         1      \__unravel_scan_int:
         2      \__unravel_convert_string:
-        3      \__unravel_convert_meaning:
+        3      \__unravel_convert_meaning:w
         4      \__unravel_scan_font_ident:
         8      \__unravel_scan_font_ident:
         9      \__unravel_scan_font_ident:
@@ -4648,12 +4958,28 @@
       { \__unravel_prev_input:x { \gtl_to_str:N \l__unravel_head_gtl } }
       { \__unravel_prev_input:V \l__unravel_head_tl }
   }
-\cs_new_protected:Npn \__unravel_convert_meaning:
+\cs_new_protected:Npn \__unravel_convert_meaning:w
+    \__unravel_prev_input_gpop:N \l__unravel_head_tl \__unravel_back_input_tl_o:
   {
     \__unravel_get_next:
     \tl_if_empty:NTF \l__unravel_head_tl
-      { \__unravel_prev_input:n { \l__unravel_head_token } }
-      { \__unravel_prev_input:V \l__unravel_head_tl }
+      {
+        \gtl_set_eq:NN \l__unravel_tmpb_gtl \l__unravel_head_gtl
+        \__unravel_prev_input_gpop:N \l__unravel_prev_input_tl
+        \exp_args:NNV \gtl_put_left:Nn \l__unravel_tmpb_gtl \l__unravel_prev_input_tl
+        \__unravel_prev_input_gpush_gtl:N \l__unravel_tmpb_gtl
+        \__unravel_print_action:x { \gtl_to_str:N \l__unravel_tmpb_gtl }
+        \__unravel_prev_input_gpop_gtl:N \l__unravel_tmpb_gtl
+        \tl_set:Nx \l__unravel_tmpa_tl { \gtl_head_do:NN \l__unravel_head_gtl \tex_meaning:D }
+        \__unravel_back_input:V \l__unravel_tmpa_tl
+        \__unravel_print_expansion:x
+          { \gtl_to_str:N \l__unravel_tmpb_gtl = \tl_to_str:N \l__unravel_tmpa_tl }
+      }
+      {
+        \__unravel_prev_input:V \l__unravel_head_tl
+        \__unravel_prev_input_gpop:N \l__unravel_head_tl
+        \__unravel_back_input_tl_o:
+      }
   }
 \cs_new_protected:Npn \__unravel_scan_pdfstrcmp:
   {
@@ -4713,7 +5039,7 @@
       }
       { % \the
         \__unravel_get_x_next:
-        \__unravel_scan_something_internal:n { 5 }
+        \__unravel_rescan_something_internal:n { 5 }
         \__unravel_prev_input_gpop:N \l__unravel_head_tl
         \__unravel_set_action_text:x
           {
@@ -4746,10 +5072,7 @@
 \__unravel_new_tex_expandable:nn { top_bot_mark }                  % 112
   { \__unravel_back_input_tl_o: }
 \__unravel_new_tex_expandable:nn { end_template }                  % 117
-  {
-    \__unravel_not_implemented:n { end-template } { } { } { }
-    \__unravel_back_input_tl_o:
-  }
+  { \__unravel_back_input_tl_o: }
 \cs_new_protected:Npn \__unravel_pass_text:
   {
     \__unravel_input_if_empty:TF
@@ -4812,6 +5135,7 @@
   }
 \cs_new_protected:Npn \__unravel_cond_pop:
   {
+    \fi:
     \int_gset:Nn \g__unravel_if_limit_int
       { \tl_head:N \g__unravel_if_limit_tl }
     \tl_gset:Nx \g__unravel_if_limit_tl
@@ -4848,7 +5172,8 @@
         {  1 } { \__unravel_test_two_chars:nn { 1 } {#1} } % ifcat
         { 12 } { \__unravel_test_ifx:n {#1} }
         { 16 } { \__unravel_test_case:n {#1} }
-        { 21 } { \__unravel_test_pdfprimitive:n {#1} } % ^^A todo and \unless
+        { 20 } { \if_true: \__unravel_test_incsname:n {#1} }
+        { 21 } { \if_true: \__unravel_test_pdfprimitive:n {#1} }
       }
       {
         \__unravel_prev_input_gpush:N \l__unravel_head_tl
@@ -4860,13 +5185,8 @@
             {  3 } % ifdim
               { \__unravel_test_two_vals:N \__unravel_scan_normal_dimen: }
             {  4 } { \__unravel_scan_int: } % ifodd
-            % {  5 } { } % ifvmode
-            % {  6 } { } % ifhmode
-            % {  7 } { } % ifmmode
-            % {  8 } { } % ifinner
-            {  9 } { \__unravel_scan_int: } % ifvoid
-            { 10 } { \__unravel_scan_int: } % ifhbox
-            { 11 } { \__unravel_scan_int: } % ifvbox
+            % {  5 } { } % if[hvm]mode, ifinner, if[tydm]dir
+            {  9 } { \__unravel_scan_int: } % ifvoid, ifhbox, ifvbox etc
             { 13 } { \__unravel_scan_int: } % ifeof
             % { 14 } { } % iftrue
             % { 15 } { } % iffalse
@@ -4874,30 +5194,30 @@
             { 18 } { \__unravel_test_ifcsname: } % ifcsname
             { 19 } % iffontchar
               { \__unravel_scan_font_ident: \__unravel_scan_int: }
-            % { 20 } { } % ifincsname % ^^A todo: something?
-            { 22 } % ifpdfabsnum
+            { 22 } % ifabsnum
               { \__unravel_test_two_vals:N \__unravel_scan_int: }
-            { 23 } % ifpdfabsdim
+            { 23 } % ifabsdim
               { \__unravel_test_two_vals:N \__unravel_scan_normal_dimen: }
+            { 24 } { \__unravel_scan_font_ident: } % ifjfont, iftfont
           }
         \__unravel_prev_input_gpop:N \l__unravel_head_tl
         \__unravel_set_action_text:x { \tl_to_str:N \l__unravel_head_tl }
         \l__unravel_head_tl \scan_stop:
-          \exp_after:wN \__unravel_cond_true:n
+          \__unravel_cond_true:NNNn
         \else:
-          \exp_after:wN \__unravel_cond_false:n
+          \__unravel_cond_false:Nn
         \fi:
         {#1}
       }
   }
-\cs_new_protected:Npn \__unravel_cond_true:n #1
+\cs_new_protected:Npn \__unravel_cond_true:NNNn #1#2#3#4
   {
-    \__unravel_change_if_limit:nn { 3 } {#1} % wait for else/fi
+    \__unravel_change_if_limit:nn { 3 } {#4} % wait for else/fi
     \__unravel_print_expansion:x { \g__unravel_action_text_str = true }
   }
-\cs_new_protected:Npn \__unravel_cond_false:n #1
+\cs_new_protected:Npn \__unravel_cond_false:Nn #1#2
   {
-    \__unravel_cond_false_loop:n {#1}
+    \__unravel_cond_false_loop:n {#2}
     \__unravel_cond_false_common:
     \__unravel_print_expansion:x
       {
@@ -4943,6 +5263,7 @@
   }
 \cs_new_protected:Npn \__unravel_test_two_chars:nn #1
   {
+    \exp_args:NNo \gtl_set:Nn \l__unravel_head_gtl { \l__unravel_head_tl }
     \__unravel_prev_input_gpush_gtl:N \l__unravel_head_gtl
     \__unravel_print_expansion:
     \__unravel_test_two_chars_get:n {#1}
@@ -4950,13 +5271,18 @@
     \__unravel_prev_input_gpop_gtl:N \l__unravel_head_gtl
     \__unravel_set_action_text:x { \gtl_to_str:N \l__unravel_head_gtl }
     \gtl_pop_left_item:NNTF \l__unravel_head_gtl \l__unravel_head_tl { } { }
+    \exp_args:No \tl_if_head_eq_meaning:nNT \l__unravel_head_tl \reverse_if:N
+      {
+        \gtl_pop_left_item:NNTF \l__unravel_head_gtl \l__unravel_head_tl { } { }
+        \tl_put_left:Nn \l__unravel_head_tl { \reverse_if:N }
+      }
     \gtl_pop_left:NN \l__unravel_head_gtl \l__unravel_tmpb_gtl
     \__unravel_test_two_chars_gtl:N \l__unravel_tmpb_gtl
     \__unravel_test_two_chars_gtl:N \l__unravel_head_gtl
     \l__unravel_head_tl \scan_stop:
-      \exp_after:wN \__unravel_cond_true:n
+      \__unravel_cond_true:NNNn
     \else:
-      \exp_after:wN \__unravel_cond_false:n
+      \__unravel_cond_false:Nn
     \fi:
   }
 \cs_new_protected:Npn \__unravel_test_two_chars_get:n #1
@@ -5001,9 +5327,9 @@
       }
     \__unravel_test_ifx_aux:NNN \l__unravel_tmpb_token \l__unravel_tmpb_gtl
       \__unravel_test_ifx_aux:w
-      \exp_after:wN \__unravel_cond_true:n
+      \__unravel_cond_true:NNNn
     \else:
-      \exp_after:wN \__unravel_cond_false:n
+      \__unravel_cond_false:Nn
     \fi:
     {#1}
   }
@@ -5029,6 +5355,7 @@
   }
 \cs_new_protected:Npn \__unravel_test_case:n #1
   {
+    \if_case:w 0 ~
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_expansion:
     \bool_if:NT \g__unravel_internal_debug_bool { \iow_term:n { {\ifcase level~#1} } }
@@ -5036,6 +5363,12 @@
     \__unravel_prev_input_get:N \l__unravel_head_tl
     \tl_set:Nx \l__unravel_head_tl { \tl_tail:N \l__unravel_head_tl }
     % ^^A does text_case_aux use prev_input_seq?
+    \int_compare:nNnF { \l__unravel_head_tl } = 0
+      {
+        \int_compare:nNnTF { \l__unravel_head_tl } > 0
+          { \fi: \if_case:w 1 ~ \or: }
+          { \fi: \if_case:w -1 ~ \else: }
+      }
     \exp_args:No \__unravel_test_case_aux:nn { \l__unravel_head_tl } {#1}
     \__unravel_prev_input_gpop:N \l__unravel_head_tl
     \__unravel_print_expansion:x { \tl_to_str:N \l__unravel_head_tl }
@@ -5062,6 +5395,10 @@
           }
       }
   }
+\cs_new_protected:Npn \__unravel_test_incsname:n #1
+  { \__unravel_not_implemented:n { ifincsname } }
+\cs_new_protected:Npn \__unravel_test_pdfprimitive:n #1
+  { \__unravel_not_implemented:n { ifpdfprimitive } }
 \cs_new_protected:Npn \__unravel_test_ifdefined:
   {
     \__unravel_input_if_empty:TF
@@ -5085,6 +5422,7 @@
   {
     \__unravel_csname_loop:
     \__unravel_prev_input:V \l__unravel_head_tl
+    \__unravel_get_lastnamedcs:
   }
 \__unravel_new_tex_expandable:nn { fi_or_else }                    % 108
   {
@@ -5200,8 +5538,8 @@
   }
 \cs_new_protected:Npn \__unravel_print_state_prev:
   {
-    \seq_set_map:NNn \l__unravel_tmpa_seq \g__unravel_prev_input_seq
-      { \__unravel_to_str:n {##1} }
+    \seq_set_map_x:NNn \l__unravel_tmpa_seq \g__unravel_prev_input_seq
+      { \__unravel_to_str:Nn ##1 }
     \seq_remove_all:Nn \l__unravel_tmpa_seq { }
     \seq_if_empty:NTF \l__unravel_tmpa_seq
       { \__unravel_print_message:nn { || ~ } { } }
@@ -5281,19 +5619,23 @@
         \__unravel_prompt:
       }
   }
-\cs_new_protected:Npn \__unravel_print_assigned_token:
+\cs_new_protected:Npn \__unravel_just_print_assigned_token:
   {
-    \__unravel_after_assignment: % ^^A todo: simplify
     \__unravel_print_assignment:x
       {
         Set~ \exp_after:wN \token_to_str:N \l__unravel_defined_tl
         = \exp_after:wN \token_to_meaning:N \l__unravel_defined_tl
       }
+  }
+\cs_new_protected:Npn \__unravel_print_assigned_token:
+  {
+    \__unravel_after_assignment:
+    \__unravel_just_print_assigned_token:
     \__unravel_omit_after_assignment:w
   }
 \cs_new_protected:Npn \__unravel_print_assigned_register:
   {
-    \__unravel_after_assignment: % ^^A todo: simplify
+    \__unravel_after_assignment:
     \__unravel_exp_args:Nx \__unravel_print_assignment:x
       {
         \exp_not:n
@@ -5571,8 +5913,9 @@
     max-input        .int_gset:N  = \g__unravel_default_max_input_int ,
     number-steps     .bool_gset:N = \g__unravel_default_number_steps_bool ,
     online           .int_gset:N  = \g__unravel_default_online_int ,
-    prompt-input     .clist_gset:N = \g__unravel_default_prompt_input_clist ,
-    trace-assigns    .bool_gset:N = \g__unravel_default_trace_assign_bool ,
+    prompt-input     .code:n
+      = \__unravel_prompt_input:Nn \g__unravel_default_prompt_input_clist {#1} ,
+    trace-assigns    .bool_gset:N = \g__unravel_default_trace_assigns_bool ,
     trace-expansion  .bool_gset:N = \g__unravel_default_trace_expansion_bool ,
     trace-other      .bool_gset:N = \g__unravel_default_trace_other_bool ,
     welcome-message  .bool_gset:N = \g__unravel_default_welcome_message_bool ,
@@ -5586,7 +5929,8 @@
     max-input        .int_gset:N  = \g__unravel_max_input_int ,
     number-steps     .bool_gset:N = \g__unravel_number_steps_bool ,
     online           .int_gset:N  = \g__unravel_online_int ,
-    prompt-input     .clist_gset:N = \g__unravel_prompt_input_clist ,
+    prompt-input     .code:n
+      = \__unravel_prompt_input:Nn \g__unravel_prompt_input_clist {#1} ,
     trace-assigns    .bool_gset:N = \g__unravel_trace_assigns_bool ,
     trace-expansion  .bool_gset:N = \g__unravel_trace_expansion_bool ,
     trace-other      .bool_gset:N = \g__unravel_trace_other_bool ,
@@ -5638,7 +5982,6 @@
     \__unravel_exit_point:
     \__unravel_print_outcome:
     \__unravel_final_test:
-    \__unravel_final_after_assignment:
     \__unravel_exit_point:
   }
 \cs_new_protected:Npn \unravel_get:nnN #1#2#3
@@ -5648,6 +5991,7 @@
   }
 \cs_new_protected:Npn \__unravel_init_key_vars:
   {
+    \sys_if_engine_luatex:T { \tl_gset:No \g__unravel_lastnamedcs_tl { \tex_lastnamedcs:D } }
     \bool_gset_eq:NN \g__unravel_explicit_prompt_bool \g__unravel_default_explicit_prompt_bool
     \bool_gset_eq:NN \g__unravel_internal_debug_bool \g__unravel_default_internal_debug_bool
     \bool_gset_eq:NN \g__unravel_number_steps_bool \g__unravel_default_number_steps_bool
@@ -5700,15 +6044,18 @@
   }
 \cs_new_protected:Npn \__unravel_final_test:
   {
-    \bool_if:nTF
+    \__unravel_input_if_empty:TF
       {
-        \tl_if_empty_p:N \g__unravel_if_limit_tl
-        && \int_compare_p:nNn \g__unravel_if_limit_int = 0
-        && \int_compare_p:nNn \g__unravel_if_depth_int = 0
-        && \seq_if_empty_p:N \g__unravel_prev_input_seq
+        \seq_if_empty:NTF \g__unravel_prev_input_seq
+          {
+            \tl_if_empty:NTF \g__unravel_if_limit_tl
+              { \int_compare:nNnF \g__unravel_if_limit_int = 0 { \__unravel_final_bad: } }
+              { \__unravel_final_conditionals: }
+          }
+          { \__unravel_final_bad: }
       }
-      { \__unravel_input_if_empty:TF { } { \__unravel_final_bad: } }
       { \__unravel_final_bad: }
+    \__unravel_final_after_assignment:
   }
 \cs_new_protected:Npn \__unravel_final_bad:
   {
@@ -5715,11 +6062,39 @@
     \__unravel_error:nnnnn { internal }
       { the-last-unravel-finished-badly } { } { } { }
   }
+\cs_new_protected:Npn \__unravel_final_conditionals:
+  {
+    \group_begin:
+    \msg_warning:nnx { unravel } { dangling-conditionals }
+      { \tl_count:N \g__unravel_if_limit_tl }
+    \group_end:
+    \tl_greverse:N \g__unravel_if_limit_tl
+    \tl_gput_right:NV \g__unravel_if_limit_tl \g__unravel_if_limit_int
+    \tl_gset:Nx \g__unravel_if_limit_tl { \tl_tail:N \g__unravel_if_limit_tl } % remove the {0}
+    \prg_replicate:nn { \tl_count:N \g__unravel_if_limit_tl } { \fi: }
+    \tl_map_function:NN \g__unravel_if_limit_tl \__unravel_final_cond_aux:n
+  }
+\cs_new:Npn \__unravel_final_cond_aux:n #1
+  {
+    \int_case:nnF {#1}
+      {
+        { 2 } { \if_false: \else: }
+        { 3 } { \if_true: }
+        { 4 } { \if_case:w 0 ~ }
+      }
+      { \__unravel_final_bad: }
+  }
 \cs_new_protected:Npn \__unravel_final_after_assignment:
   {
     \gtl_if_empty:NF \g__unravel_after_assignment_gtl
       { \gtl_head_do:NN \g__unravel_after_assignment_gtl \tex_afterassignment:D }
   }
+\msg_new:nnnn { unravel } { prev-input }
+  { Internal~error:~unexpected~type~of~``prev_input''~entry. }
+  {
+    Found~type~#2~instead~of~#1~to~assign~to~variable~#3.~Contents:\\
+    \iow_indent:n {#4}
+  }
 \msg_new:nnn { unravel } { unknown-primitive }
   { Internal~error:~the~primitive~'#1'~is~not~known. }
 \msg_new:nnn { unravel } { extra-fi-or-else }
@@ -5810,6 +6185,8 @@
     Some~TeX~command~expects~input~beyond~the~end~of~
     the~argument~of~\iow_char:N\\unravel.
   }
+\msg_new:nnn { unravel } { dangling-conditionals }
+  { Attempting~to~issue~#1~dangling~conditionals. }
 \__unravel_tex_msg_new:nnn { forbidden-case }
   {
     You~can't~use~`\exp_after:wN \token_to_str:N \l__unravel_head_tl'~in~
@@ -5891,6 +6268,17 @@
     not~appear~between~\token_to_str:c{csname}~and~
     \token_to_str:c{endcsname}.
   }
+\__unravel_tex_msg_new:nnn { missing-delim }
+  { Missing~delimiter~(.~inserted) }
+  {
+    I~was~expecting~to~see~something~like~`('~or~`\token_to_str:N\{'~or~
+    `\token_to_str:N\}'~here.~If~you~typed,~e.g.,~
+    `\{'~instead~of~`\token_to_str:N\{',~you~
+    should~probably~delete~the~`\{'~by~typing~`1'~now,~so~that~
+    braces~don't~get~unbalanced.~Otherwise~just~proceed.~
+    Acceptable~delimiters~are~characters~whose~\token_to_str:c{delcode}~is~
+    nonnegative,~or~you~can~use~`\token_to_str:c{delimiter}~<delimiter~code>'.
+  }
 \__unravel_tex_msg_new:nnn { cannot-read }
   { ***~(cannot~\iow_char:N\\read~from~terminal~in~nonstop~modes) }
   { }



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