diff options
author | Karl Berry <karl@freefriends.org> | 2011-08-12 23:14:34 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-08-12 23:14:34 +0000 |
commit | c9172879c19139ba8d262e615a535073caea2e54 (patch) | |
tree | 3d907d4933b43fbc204a7069106fb6715601824f /Master/texmf-dist/source/latex | |
parent | 3affad3394ee81c3f5ba136242d5d56949254515 (diff) |
l3kernel (11aug11)
git-svn-id: svn://tug.org/texlive/trunk@23524 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/expl3.dtx | 6 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx | 59 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx | 61 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3box.dtx | 8 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3final.dtx | 4 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3int.dtx | 29 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3prg.dtx | 5 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3skip.dtx | 11 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3tl.dtx | 234 |
9 files changed, 319 insertions, 98 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx index 443c87b3916..9f7a8a698aa 100644 --- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx @@ -35,8 +35,10 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: expl3.dtx 2478 2011-06-19 21:34:23Z joseph $ - {L3 Experimental code bundle wrapper} +\def\ExplFileName{expl3} +\def\ExplFileDescription{L3 Experimental code bundle wrapper} +\def\ExplFileDate{2011/08/10} +\def\ExplFileVersion{2535} %</driver|package> %<*driver> \documentclass[full]{l3doc} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx index 8e175a2e74d..5fe3d23d968 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3alloc.dtx 2478 2011-06-19 21:34:23Z joseph $ +\GetIdInfo$Id: l3alloc.dtx 2528 2011-08-09 09:10:06Z joseph $ {L3 Experimental register allocation} %</driver|package> %<*driver> @@ -165,6 +165,63 @@ } % \end{macrocode} % \end{macro} +% +% \begin{macro}{\int_eval:n} +% For bootstrapping purposes, a definition of \cs{int_eval:n} is needed +% in terms of primitives. This is replaced in \pkg{l3int} with a clearer +% one. +% \begin{macrocode} +\cs_new:Npn \int_eval:n #1 { \tex_number:D \etex_numexpr:D #1 \scan_stop: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% {box_new:N, \dim_new:N, \int_new:N, \muskip_new:N \skip_new:N} +% To get everything to work correctly for inserts, some register types +% need to have their allocators set up \enquote{early}. It therefore +% makes sense to collect most of them together here. +% \begin{macrocode} +\alloc_new:nnnN { box } \c_zero \c_max_register_int \tex_mathchardef:D +\alloc_new:nnnN { dim } \c_zero \c_max_register_int \tex_dimendef:D +\alloc_new:nnnN { int } { 11 } \c_max_register_int \tex_countdef:D +\alloc_new:nnnN { muskip } \c_zero \c_max_register_int \tex_muskipdef:D +\alloc_new:nnnN { skip } \c_zero \c_max_register_int \tex_skipdef:D +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\insert_new:N} +% \begin{macro}[aux]{\alloc_reserve_insert:n} +% For inserts, there is a need to reserve space in various other registers. +% \begin{macrocode} +\alloc_new:nnnN { insert } { 221 } { 254 } \tex_chardef:D +\group_begin: + \cs_set_protected_nopar:Npn \alloc_reserve_insert:n #1 + { + \tex_ifnum:D #1 > \c_insert_allocation_max_tl \scan_stop: + \exp_after:wN \use_none:n + \tex_else:D + \exp_after:wN \use:n + \tex_fi:D + { + \seq_put_right:Nn \g_box_allocation_seq {#1} + \seq_put_right:Nn \g_dim_allocation_seq {#1} + \seq_put_right:Nn \g_int_allocation_seq {#1} + \seq_put_right:Nn \g_skip_allocation_seq {#1} + \exp_args:Nf \alloc_reserve_insert:n + { \etex_numexpr:D #1 + 1 \scan_stop: } + } + } + \alloc_reserve_insert:n { 221 } +\group_end: +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% Box $255$ is reserved by \TeX{} for output, so is protected here from +% use by the allocator. +% \begin{macrocode} +\seq_put_right:Nn \g_box_allocation_seq { 255 } +% \end{macrocode} % % \begin{macro}[int]{\alloc_reg:nNN} % This internal macro performs the actual allocation. diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx index 69aaf46357b..ee971e3b09b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx @@ -34,13 +34,56 @@ %% ----------------------------------------------------------------------- % %<*package> -\def\GetIdInfo$% - Id: #1 #2 #3-#4-#5 #6 #7 $#8% +\protected\def\GetIdInfo + { + \begingroup + \catcode 32 = 10 \relax + \GetIdInfoAuxI + } +\protected\def\GetIdInfoAuxI$#1$#2% + { + \def\tempa{#1}% + \def\tempb{Id}% + \ifx\tempa\tempb + \def\tempa + {% + \endgroup + \def\ExplFileDate{9999/99/99}% + \def\ExplFileDescription{#2}% + \def\ExplFileName{[unknown name]}% + \def\ExplFileExtension{[unknown extension]}% + \def\ExplFileVersion{999}% + }% + \else + \def\tempa + {% + \endgroup + \GetIdInfoAuxII$#1${#2}% + }% + \fi + \tempa + } +\protected\def\GetIdInfoAuxII$#1 #2.#3 #4 #5 #6 #7 #8$#9% {% - \def\ExplFileDate{#3/#4/#5}% - \def\ExplFileVersion{#2}% + \def\ExplFileName{#2}% + \def\ExplFileExtension{#3}% + \def\ExplFileVersion{#4}% + \def\ExplFileDescription{#9}% + \GetIdInfoAuxIII#5\relax#3\relax#5\relax#6\relax } -\GetIdInfo$Id: l3bootstrap.dtx 2478 2011-06-19 21:34:23Z joseph $ +\protected\def\GetIdInfoAuxIII#1#2#3#4#5#6\relax + {% + \ifx#5/% + \expandafter\GetIdInfoAuxCVS + \else + \expandafter\GetIdInfoAuxSVN + \fi + } +\protected\def\GetIdInfoAuxCVS#1,v\relax#2\relax#3\relax + {\def\ExplFileDate{#2}} +\protected\def\GetIdInfoAuxSVN#1\relax#2-#3-#4\relax#5Z\relax + {\def\ExplFileDate{#2/#3/#4}} +\GetIdInfo$Id: l3bootstrap.dtx 2519 2011-08-08 09:35:54Z mittelba $ {L3 experimental bootstrap code} %</package> %<*driver> @@ -332,10 +375,10 @@ \def\tempa {% \endgroup - \def\ExplFileDate{0000/00/00}% + \def\ExplFileDate{9999/99/99}% \def\ExplFileDescription{#2}% - \def\ExplFileName{[unknown~name]}% - \def\ExplFileVersion{000}% + \def\ExplFileName{[unknown name]}% + \def\ExplFileVersion{999}% }% \else \def\tempa @@ -644,4 +687,4 @@ % % \end{implementation} % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx index 1947f85b356..85313ce8791 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3box.dtx 2478 2011-06-19 21:34:23Z joseph $ +\GetIdInfo$Id: l3box.dtx 2526 2011-08-09 08:58:42Z joseph $ {L3 Experimental boxes} %</driver|package> %<*driver> @@ -723,7 +723,7 @@ \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} \package_check_loaded_expl: -%<*initex|package> +%</package> % \end{macrocode} % % The code in this module is very straight forward so I'm not going to @@ -737,10 +737,6 @@ % Defining a new \meta{box} register: remember that box $255$ is not % generally available. % \begin{macrocode} -%<*initex> -\alloc_new:nnnN { box } \c_zero \c_max_register_int \tex_mathchardef:D -\seq_put_right:Nn \g_box_allocation_seq {255} -%</initex> %<*package> \cs_new_protected:Npn \box_new:N #1 { diff --git a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx index bc37e2aaee4..1645cbcd487 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3final.dtx 2478 2011-06-19 21:34:23Z joseph $ +\GetIdInfo$Id: l3final.dtx 2499 2011-07-29 12:49:30Z joseph $ {L3 Experimental format finalisation} %</driver|package> %<*driver> @@ -95,7 +95,7 @@ { \char_set_catcode_space:n { 9 } \char_set_catcode_space:n { 32 } - \char_set_catcode_math_subscript:n { 94 } + \char_set_catcode_math_subscript:n { 95 } \char_set_catcode_other:n { 58 } \char_set_catcode_active:n { 126 } \tex_endlinechar:D = 13 \scan_stop: diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx index 70264286d27..91dc8e798ce 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3int.dtx 2478 2011-06-19 21:34:23Z joseph $ +\GetIdInfo$Id: l3int.dtx 2526 2011-08-09 08:58:42Z joseph $ {L3 Experimental integers} %</driver|package> %<*driver> @@ -930,12 +930,12 @@ % Here are the remaining primitives for number comparisons and % expressions. % \begin{macrocode} -\cs_set_eq:NN \int_value:w \tex_number:D -\cs_set_eq:NN \int_eval:w \etex_numexpr:D -\cs_new_eq:NN \int_eval_end: \tex_relax:D -\cs_new_eq:NN \if_num:w \tex_ifnum:D -\cs_set_eq:NN \if_int_odd:w \tex_ifodd:D -\cs_new_eq:NN \if_case:w \tex_ifcase:D +\cs_new_eq:NN \int_value:w \tex_number:D +\cs_new_eq:NN \int_eval:w \etex_numexpr:D +\cs_new_eq:NN \int_eval_end: \tex_relax:D +\cs_new_eq:NN \if_num:w \tex_ifnum:D +\cs_new_eq:NN \if_int_odd:w \tex_ifodd:D +\cs_new_eq:NN \if_case:w \tex_ifcase:D % \end{macrocode} % \end{macro} % \end{macro} @@ -948,10 +948,16 @@ % % \begin{macro}{\int_eval:n} % Wrapper for \cs{int_eval:w}. Can be used in an integer expression -% or directly in the input stream. +% or directly in the input stream. In format mode, there is already +% a definition in \pkg{l3alloc} for bookstrapping, which is therefore +% corrected to the \enquote{real} version here. % \begin{macrocode} -\cs_new:Npn \int_eval:n #1 - { \int_value:w \int_eval:w #1 \int_eval_end: } +%<*initex> +\cs_set:Npn \int_eval:n #1 { \int_value:w \int_eval:w #1 \int_eval_end: } +%</initex> +%<*package> +\cs_new:Npn \int_eval:n #1 { \int_value:w \int_eval:w #1 \int_eval_end: } +%</package> % \end{macrocode} % \end{macro} % @@ -1058,9 +1064,6 @@ % Two ways to do this: one for the format and one for the \LaTeXe{} % package. % \begin{macrocode} -%<*initex> -\alloc_new:nnnN { int } { 11 } { \c_max_register_int } \tex_countdef:D -%</initex> %<*package> \cs_new_protected_nopar:Npn \int_new:N #1 { diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx index b4cf9368f2a..58175b05561 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3prg.dtx 2495 2011-07-06 16:57:08Z bruno $ +\GetIdInfo$Id: l3prg.dtx 2509 2011-08-07 11:21:26Z bruno $ {L3 Experimental control structures} %</driver|package> %<*driver> @@ -1767,7 +1767,8 @@ % % \begin{macro}[pTF]{\mode_if_math:} % \UnitTested -% For testing math mode: without \cs{} things go wrong in alignments. +% For testing math mode: without \cs{scan_align_safe_stop:} +% things go wrong in alignments. % \begin{macrocode} \prg_new_conditional:Npnn \mode_if_math: { p , T , F , TF } { diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx index ecd3ca2e397..9145e7d59cf 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3skip.dtx 2478 2011-06-19 21:34:23Z joseph $ +\GetIdInfo$Id: l3skip.dtx 2526 2011-08-09 08:58:42Z joseph $ {L3 Experimental dimensions and skips} %</driver|package> %<*driver> @@ -928,9 +928,6 @@ % \begin{macro}{\dim_new:N,\dim_new:c} % Allocating \meta{dim} registers \ldots % \begin{macrocode} -%<*initex> -\alloc_new:nnnN { dim } \c_zero \c_max_register_int \tex_dimendef:D -%</initex> %<*package> \cs_new_protected_nopar:Npn \dim_new:N #1 { @@ -1327,9 +1324,6 @@ % \begin{macro}{\skip_new:N,\skip_new:c} % Allocation of a new internal registers. % \begin{macrocode} -%<*initex> -\alloc_new:nnnN { skip } \c_zero \c_max_register_int \tex_skipdef:D -%</initex> %<*package> \cs_new_protected_nopar:Npn \skip_new:N #1 { @@ -1526,9 +1520,6 @@ % \begin{macro}{\muskip_new:N, \muskip_new:c} % And then we add muskips. % \begin{macrocode} -%<*initex> -\alloc_new:nnnN { muskip } \c_zero \c_max_register_int \tex_muskipdef:D -%</initex> %<*package> \cs_new_protected_nopar:Npn \muskip_new:N #1 { diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index a7f292d14c7..149f4a487ba 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3names} -\GetIdInfo$Id: l3tl.dtx 2498 2011-07-09 17:51:47Z joseph $ +\GetIdInfo$Id: l3tl.dtx 2534 2011-08-10 18:21:44Z joseph $ {L3 Experimental token lists} %</driver|package> %<*driver> @@ -768,44 +768,87 @@ % \begin{syntax} % \cs{tl_head:n} \Arg{tokens} % \end{syntax} -% Leaves only the first \meta{token} in \meta{tokens} in the input -% stream, discarding the remainder. +% Leaves in the input stream the first non-space token from the +% \meta{tokens}. Any leading space tokens will be discarded, and thus for +% example +% \begin{verbatim} +% \tl_head:n { abc } +% \end{verbatim} +% and +% \begin{verbatim} +% \tl_head:n { ~ abc } +% \end{verbatim} +% will both leave |a| in the input stream. +% An empty list of \meta{tokens} or one which consists +% only of space (category code $10$) tokens will result in \cs{tl_head:n} +% leaving nothing in the input stream. % \end{function} % % \begin{function}[EXP]{\tl_head:w} % \begin{syntax} -% \cs{tl_head:w} \Arg{tokens} \cs{q_stop} +% \cs{tl_head:w} \meta{tokens} \cs{q_stop} % \end{syntax} -% Leaves only the first \meta{token} in \meta{tokens} in the input -% stream, discarding the remainder. This function requires only a -% single expansion, and so is suitable for use inside an -% \texttt{o}-type expansion. In general \cs{tl_head:n} should be -% preferred. +% Leaves in the input stream the first non-space token from the +% \meta{tokens}. An empty list of \meta{tokens} or one which consists +% only of space (category code $10$) tokens will result in an error, and +% thus \meta{tokens} must \emph{not} be \enquote{blank} as determined by +% \cs{tl_if_blank:n(TF)}. This function requires only a single expansion, +% and thus is suitable for use within an \texttt{o}-type expansion. In +% general, \cs{tl_head:n} should be preferred if the number of expansions +% is not critical. +% \end{function} +% +% \begin{function}[EXP]{\str_head:n} +% \begin{syntax} +% \cs{str_head:n} \Arg{tokens} +% \end{syntax} +% Converts the \meta{tokens} into a string, as described for +% \cs{tl_to_str:n}, and then leaves the first character of this string +% in the input stream; the first character may be a space. If the +% \meta{tokens} argument is entirely empty, \cs{scan_stop:} will be left in +% the input stream. % \end{function} % % \begin{function}[EXP]{\tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f} % \begin{syntax} % \cs{tl_tail:n} \Arg{tokens} % \end{syntax} -% Discards the first \meta{token} of the \meta{tokens} and leaves the -% remainder in the input stream. +% Discards the all leading space tokens and the first non-space token +% in the \meta{tokens}, and leaves the remaining tokens in the +% input stream. Thus for example +% \begin{verbatim} +% \tl_tail:n { abc } +% \end{verbatim} +% and +% \begin{verbatim} +% \tl_tail:n { ~ abc } +% \end{verbatim} +% will both leave |bc| in the input stream. +% An empty list of \meta{tokens} or one which consists +% only of space (category code $10$) tokens will result in \cs{tl_tail:n} +% leaving nothing in the input stream. % \end{function} % % \begin{function}[EXP]{\tl_tail:w} % \begin{syntax} % \cs{tl_tail:w} \Arg{tokens} \cs{q_stop} % \end{syntax} -% Discards the first \meta{token} of the \meta{tokens} and leaves the -% remainder in the input stream. This function requires only a -% single expansion, and so is suitable for use inside an -% \texttt{o}-type expansion. In general \cs{tl_tail:n} should be -% preferred. +% Discards the all leading space tokens and the first non-space token +% in the \meta{tokens}, and leaves the remaining tokens in the +% input stream. +% An empty list of \meta{tokens} or one which consists +% only of space (category code $10$) tokens will result in an error, and +% thus \meta{tokens} must \emph{not} be \enquote{blank} as determined by +% \cs{tl_if_blank:n(TF)}. This function requires only a single expansion, +% and thus is suitable for use within an \texttt{o}-type expansion. In +% general, \cs{tl_tail:n} should be preferred if the number of expansions +% is not critical. % \end{function} % % \begin{function}[EXP,pTF]{\tl_if_head_eq_catcode:nN} % \begin{syntax} -% \cs{tl_if_head_eq_catcode_p:n} \Arg{token list} \meta{test token} -% \cs{tl_if_head_eq_catcode:nTF} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_catcode_p:nN} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_catcode:nNTF} \Arg{token list} \meta{test token} % ~~\Arg{true code} \Arg{false code} % \end{syntax} % Tests if the first \meta{token} in the \meta{token list} has the same @@ -820,8 +863,8 @@ % \begin{function}[EXP,pTF] % {\tl_if_head_eq_charcode:nN, \tl_if_head_eq_charcode:fN} % \begin{syntax} -% \cs{tl_if_head_eq_charcode_p:n} \Arg{token list} \meta{test token} -% \cs{tl_if_head_eq_charcode:nTF} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_charcode_p:nN} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_charcode:nNTF} \Arg{token list} \meta{test token} % ~~\Arg{true code} \Arg{false code} % \end{syntax} % Tests if the first \meta{token} in the \meta{token list} has the same @@ -835,8 +878,8 @@ % % \begin{function}[EXP,pTF]{\tl_if_head_eq_meaning:nN} % \begin{syntax} -% \cs{tl_if_head_eq_meaning_p:n} \Arg{token list} \meta{test token} -% \cs{tl_if_head_eq_meaning:nTF} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_meaning_p:nN} \Arg{token list} \meta{test token} +% \cs{tl_if_head_eq_meaning:nNTF} \Arg{token list} \meta{test token} % ~~\Arg{true code} \Arg{false code} % \end{syntax} % Tests if the first \meta{token} in the \meta{token list} has the same @@ -976,7 +1019,7 @@ % ~~\Arg{true code} \Arg{false code} % \end{syntax} % Tests if the token list consists of exactly one token, i.e., -% is either a single space character or a single ``normal'' token. +% is either a single space character or a single \enquote{normal} token. % Token groups are not single tokens. The branching % versions leaves either \meta{true code} or \meta{false code} % in the input stream, as appropriate to the truth of the test and @@ -1922,12 +1965,16 @@ % \begin{macro}{\tl_head:w} % \begin{macro}{\tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f} % \begin{macro}{\tl_tail:w} -% These functions pick up either the head or the tail of a list. +% These functions pick up either the head or the tail of a list. The +% \texttt{n}-type implementation needs a test in order to avoid run-away +% arguments occurring with blank input. % \begin{macrocode} -\cs_new:Npn \tl_head:n #1 { \tl_head:w #1 \q_stop } -\cs_new:Npn \tl_tail:n #1 { \tl_tail:w #1 \q_stop } \cs_new:Npn \tl_head:w #1#2 \q_stop {#1} \cs_new:Npn \tl_tail:w #1#2 \q_stop {#2} +\cs_new:Npn \tl_head:n #1 + { \tl_if_blank:nF {#1} { \tl_head:w #1 \q_stop } } +\cs_new:Npn \tl_tail:n #1 + { \tl_if_blank:nF {#1} { \tl_tail:w #1 \q_stop } } \cs_generate_variant:Nn \tl_head:n { V , v , f } \cs_generate_variant:Nn \tl_tail:n { V , v , f } % \end{macrocode} @@ -1936,54 +1983,135 @@ % \end{macro} % \end{macro} % +% \begin{macro}{\str_head:n} +% \begin{macro}[aux]{\str_head_aux:w} +% After \cs{tl_to_str:n}, we have a list of character tokens, +% all with category code 12, except the space, which has category +% code 10. Directly using \cs{tl_head:w} would thus lose leading spaces. +% Instead, we take an argument delimited by an explicit space, and +% then only use \cs{tl_head:w}. If the string started with a +% space, then the argument of \cs{str_head_aux:w} is empty, and +% the function correctly returns a space character. Otherwise, +% it returns the first token of |#1|, which is the first token +% of the string. If the string is empty, we return +% \cs{scan_stop:}. +% \begin{macrocode} +\cs_new:Npn \str_head:n #1 + { + \exp_after:wN \str_head_aux:w + \tl_to_str:n {#1} + { \scan_stop: } ~ \q_stop + } +\cs_new_nopar:Npn \str_head_aux:w #1 ~ % + { \tl_head:w #1 { ~ } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macro}[pTF]{\tl_if_head_eq_meaning:nN} % \begin{macro}[pTF]{\tl_if_head_eq_charcode:nN} % \begin{macro}[pTF]{\tl_if_head_eq_charcode:fN} % \begin{macro}[pTF]{\tl_if_head_eq_catcode:nN} -% When we want to check if the first token of a list equals something -% specific it is usually either to see if it is a control sequence or -% a character. Hence we make two different functions as the internal -% test is different. -% \cs{tl_if_head_meaning_eq:nNTF} uses \cs{if_meaning:w} and will -% consider the tokens |b|$\sb{11}$ and |b|$\sb{12}$ different. -% \cs{tl_if_head_char_eq:nNTF} on the other hand only compares -% character codes so would regard |b|$\sb{11}$ and |b|$\sb{12}$ as -% equal but would also regard two primitives as equal. +% Accessing the first token of a token list is tricky in two cases: +% when it has category code 1 (begin-group token), or when it is +% an explicit space, with category code 10 and character code 32. +% +% Forgetting temporarily about this issue we would use the +% following test in \cs{tl_if_head_eq_charcode:nN}. Here, +% an empty |#1| argument yields \cs{q_nil}, otherwise the +% first token of the token list. +% \begin{verbatim} +% \if_charcode:w +% \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop +% \exp_not:N #2 +% \end{verbatim} +% The special cases are detected by comparing |#1| with +% \cs{use:n}~|#1| (the extra |?| takes care of empty arguments). +% In those cases, the first token is a character, and +% since we only care about its character code, we can +% use \cs{str_head:n} to access it (this works even if +% it is a space character). % \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_head_eq_meaning:nN #1#2 { p , T , F , TF } +\prg_new_conditional:Npnn \tl_if_head_eq_charcode:nN #1#2 { p , T , F , TF } { - \exp_after:wN \if_meaning:w \tl_head:w #1 \q_stop #2 + \if_charcode:w + \exp_not:N #2 + \str_if_eq:onTF { \use:n #1 ? } { #1 ? } + { \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop } + { \str_head:n {#1} } \prg_return_true: \else: \prg_return_false: \fi: } +\cs_generate_variant:Nn \tl_if_head_eq_charcode_p:nN { f } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNTF { f } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNT { f } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNF { f } % \end{macrocode} -% For the charcode and catcode versions we insert |\exp_not:N| in -% front of both tokens. If you need them to expand fully as \TeX{} -% does itself with these you can use an |f| type expansion. +% For \cs{tl_if_head_eq_catcode:nN}, again we detect special +% cases with a \cs{str_if_eq:onTF} test. Then we need to test +% if the first token is a begin-group token or an explicit +% space token, and produce the relevant token, either +% \cs{c_group_begin_token} or \cs{c_space_token}. % \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_head_eq_charcode:nN #1#2 { p , T , F , TF } +\prg_new_conditional:Npnn \tl_if_head_eq_catcode:nN #1 #2 { p , T , F , TF } { - \exp_after:wN \if:w - \exp_after:wN \exp_not:N \tl_head:w #1 \q_stop \exp_not:N #2 + \if_catcode:w + \exp_not:N #2 + \str_if_eq:onTF { \use:n #1 ? } { #1 ? } + { \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop } + { + \tl_if_head_begin_group:nTF {#1} + { \c_group_begin_token } + { \c_space_token } + } \prg_return_true: \else: \prg_return_false: \fi: - } -\cs_generate_variant:Nn \tl_if_head_eq_charcode_p:nN { f } -\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNTF { f } -\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNT { f } -\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNF { f } + } % \end{macrocode} -% And now catcodes: +% For \cs{tl_if_head_eq_meaning:nN}, again, detect special cases. +% In the normal case, use \cs{tl_head:w}, with no \cs{exp_not:N} +% this time, since \cs{if_meaning:w} causes no expansion. +% In the special cases, we know that the first token is a character, +% hence \cs{if_charcode:w} and \cs{if_catcode:w} together are enough. +% We combine them in some order, hopefully faster than the reverse. % \begin{macrocode} -\prg_new_conditional:Npnn \tl_if_head_eq_catcode:nN #1#2 { p , T , F , TF } +\prg_new_conditional:Npnn \tl_if_head_eq_meaning:nN #1#2 { p , T , F , TF } { - \exp_after:wN \if_catcode:w \exp_after:wN \exp_not:N - \tl_head:w #1 \q_stop \exp_not:N #2 - \prg_return_true: \else: \prg_return_false: \fi: + \str_if_eq:onTF { \use:n #1 ? } { #1 ? } + { \tl_if_head_eq_meaning_aux_normal:nN } + { \tl_if_head_eq_meaning_aux_special:nN } + {#1} #2 + } +\cs_new:Npn \tl_if_head_eq_meaning_aux_normal:nN #1 #2 + { + \exp_after:wN \if_meaning:w \tl_head:w #1 \q_nil \q_stop #2 + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_new:Npn \tl_if_head_eq_meaning_aux_special:nN #1 #2 + { + \if_charcode:w \str_head:n {#1} \exp_not:N #2 + \exp_after:wN \use:n + \else: + \prg_return_false: + \exp_after:wN \use_none:n + \fi: + { + \if_catcode:w \exp_not:N #2 + \tl_if_head_begin_group:nTF {#1} + { \c_group_begin_token } + { \c_space_token } + \prg_return_true: + \else: + \prg_return_false: + \fi: + } } % \end{macrocode} % \end{macro} |