diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3str.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3str.dtx | 458 |
1 files changed, 74 insertions, 384 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx index 245be5a85ce..4cf93f4d10b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx @@ -29,7 +29,7 @@ % \fi % % \title{^^A -% The \pkg{l3str} package\\Strings^^A +% The \pkg{l3str} package: Strings^^A % } % % \author{^^A @@ -41,7 +41,7 @@ % }^^A % } % -% \date{Released 2018/03/05} +% \date{Released 2018-04-30} % % \maketitle % @@ -203,7 +203,7 @@ % var} are not automatically converted to a string. % \end{function} % -% \subsection{Modifying string variables} +% \section{Modifying string variables} % % \begin{function}[added = 2017-10-08] % { @@ -269,7 +269,7 @@ % results in \cs{l_tmpa_str} containing \texttt{abcd}. % \end{function} % -% \subsection{String conditionals} +% \section{String conditionals} % % \begin{function}[EXP, pTF, added = 2015-09-18] % {\str_if_exist:N, \str_if_exist:c} @@ -799,70 +799,6 @@ % code and so should only be used for short-term storage. % \end{variable} % -% \subsection{Internal string functions} -% -% \begin{function}[EXP]{\__str_if_eq_x:nn} -% \begin{syntax} -% \cs{__str_if_eq_x:nn} \Arg{tl_1} \Arg{tl_2} -% \end{syntax} -% Compares the full expansion of two \meta{token lists} on a character by -% character basis, and is \texttt{true} if the two lists contain the same -% characters in the same order. Leaves |0| in the input stream if the -% condition is true, and |+1| or |-1| otherwise. -% \end{function} -% -% \begin{function}{\__str_if_eq_x_return:nn} -% \begin{syntax} -% \cs{__str_if_eq_x_return:nn} \Arg{tl_1} \Arg{tl_2} -% \end{syntax} -% Compares the full expansion of two \meta{token lists} on a character by -% character basis, and is \texttt{true} if the two lists contain the same -% characters in the same order. Either \cs{prg_return_true:} or -% \cs{prg_return_false:} is then left in the input stream. This is a version -% of \cs{str_if_eq_x:nnTF} coded for speed. -% \end{function} -% -% \begin{function}[EXP]{\__str_to_other:n} -% \begin{syntax} -% \cs{__str_to_other:n} \Arg{token list} -% \end{syntax} -% Converts the \meta{token list} to a \meta{other string}, where -% spaces have category code \enquote{other}. This function can be -% \texttt{f}-expanded without fear of losing a leading space, since -% spaces do not have category code $10$ in its result. It takes a -% time quadratic in the character count of the string. -% \end{function} -% -% \begin{function}[rEXP]{\__str_to_other_fast:n} -% \begin{syntax} -% \cs{__str_to_other_fast:n} \Arg{token list} -% \end{syntax} -% Same behaviour \cs{__str_to_other:n} but only restricted-expandable. -% It takes a time linear in the character count of the string. -% It is used for \cs{iow_wrap:nnnN}. -% \end{function} -% -% \begin{function}[EXP]{\__str_count:n} -% \begin{syntax} -% \cs{__str_count:n} \Arg{other string} -% \end{syntax} -% This function expects an argument that is entirely made of -% characters with category \enquote{other}, as produced by -% \cs{__str_to_other:n}. It leaves in the input stream the number of -% character tokens in the \meta{other string}, faster than the -% analogous \cs{str_count:n} function. -% \end{function} -% -% \begin{function}[EXP]{\__str_range:nnn} -% \begin{syntax} -% \cs{__str_range:nnn} \Arg{other string} \Arg{start index} \Arg{end index} -% \end{syntax} -% Identical to \cs{str_range:nnn} except that the first argument is -% expected to be entirely made of characters with category -% \enquote{other}, as produced by \cs{__str_to_other:n}, and the -% result is also an \meta{other string}. -% \end{function} -% % \end{documentation} % % \begin{implementation} @@ -955,8 +891,11 @@ \tl_if_blank:nF {#1} { \cs_new_protected:cpx { str_ #1 :Nn } ##1##2 - { \exp_not:c { tl_ #1 :Nx } ##1 { \exp_not:N \tl_to_str:n {##2} } } - \exp_args:Nc \cs_generate_variant:Nn { str_ #1 :Nn } { Nx , cn , cx } + { + \exp_not:c { tl_ #1 :Nx } ##1 + { \exp_not:N \tl_to_str:n {##2} } + } + \cs_generate_variant:cn { str_ #1 :Nn } { Nx , cn , cx } \@@_tmp:n } } @@ -1079,10 +1018,14 @@ % } % More copy-paste! % \begin{macrocode} -\prg_new_eq_conditional:NNn \str_if_exist:N \tl_if_exist:N { p , T , F , TF } -\prg_new_eq_conditional:NNn \str_if_exist:c \tl_if_exist:c { p , T , F , TF } -\prg_new_eq_conditional:NNn \str_if_empty:N \tl_if_empty:N { p , T , F , TF } -\prg_new_eq_conditional:NNn \str_if_empty:c \tl_if_empty:c { p , T , F , TF } +\prg_new_eq_conditional:NNn \str_if_exist:N \tl_if_exist:N + { p , T , F , TF } +\prg_new_eq_conditional:NNn \str_if_exist:c \tl_if_exist:c + { p , T , F , TF } +\prg_new_eq_conditional:NNn \str_if_empty:N \tl_if_empty:N + { p , T , F , TF } +\prg_new_eq_conditional:NNn \str_if_empty:c \tl_if_empty:c + { p , T , F , TF } % \end{macrocode} % \end{macro} % @@ -1093,9 +1036,8 @@ % is that we do not \emph{always} use the primitive, the correct approach % is to wrap up in a function with defined behaviour. That's done by % providing a wrapper and then redefining in the \LuaTeX{} case. Note that -% the necessary Lua code is covered in \pkg{l3boostrap}: long-term this may -% need to go into a separate Lua file, but at present it's somewhere that -% spaces are not skipped for ease-of-input. The need to detokenize and force +% the necessary Lua code is loaded in \pkg{l3boostrap}. +% The need to detokenize and force % expansion of input arises from the case where a |#| token is used in the % input, \emph{e.g.}~|\__str_if_eq_x:nn {#} { \tl_to_str:n {#} }|, which % otherwise would fail as \cs{luatex_luaescapestring:D} does not double @@ -1104,9 +1046,11 @@ \cs_new:Npn \@@_if_eq_x:nn #1#2 { \pdftex_strcmp:D {#1} {#2} } \cs_if_exist:NT \luatex_luatexversion:D { + \cs_set_eq:NN \lua_escape_x:n \luatex_luaescapestring:D + \cs_set_eq:NN \lua_now_x:n \luatex_directlua:D \cs_set:Npn \@@_if_eq_x:nn #1#2 { - \luatex_directlua:D + \lua_now_x:n { l3kernel.strcmp ( @@ -1117,34 +1061,14 @@ } \cs_new:Npn \@@_escape_x:n #1 { - \luatex_luaescapestring:D - { - \etex_detokenize:D \exp_after:wN { \luatex_expanded:D {#1} } - } + \lua_escape_x:n + { \__kernel_tl_to_str:w \use_x:n { {#1} } } } } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}[EXP]{\@@_if_eq_x_return:nn} -% It turns out that we often need to compare a token list -% with the result of applying some function to it, and -% return with \cs{prg_return_true/false:}. This test is -% similar to \cs{str_if_eq:nnTF} (see \pkg{l3str}), -% but is hard-coded for speed. -% \begin{macrocode} -\cs_new:Npn \@@_if_eq_x_return:nn #1 #2 - { - \if_int_compare:w \@@_if_eq_x:nn {#1} {#2} = 0 \exp_stop_f: - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -% \end{macrocode} -% \end{macro} -% % \begin{macro}[pTF, EXP] % { % \str_if_eq:nn, \str_if_eq:Vn, \str_if_eq:on, \str_if_eq:nV, @@ -1180,7 +1104,8 @@ % \begin{macrocode} \prg_new_conditional:Npnn \str_if_eq:NN #1#2 { p , TF , T , F } { - \if_int_compare:w \@@_if_eq_x:nn { \tl_to_str:N #1 } { \tl_to_str:N #2 } + \if_int_compare:w + \@@_if_eq_x:nn { \tl_to_str:N #1 } { \tl_to_str:N #2 } = 0 \exp_stop_f: \prg_return_true: \else: \prg_return_false: \fi: } \prg_generate_conditional_variant:Nnn \str_if_eq:NN @@ -1278,7 +1203,8 @@ { \@@_case_end:nw {#3} } { \@@_case_x:nw {#1} } } -\cs_new_eq:NN \@@_case_end:nw \__prg_case_end:nw +\cs_new:Npn \@@_case_end:nw #1#2#3 \q_mark #4#5 \q_stop + { \exp_end: #1 #4 } % \end{macrocode} % \end{macro} % \end{macro} @@ -1299,7 +1225,7 @@ % The inline and variable mappings are similar to the usual token list % mappings but start out by turning the argument to an ``other % string''. Doing the same for the expandable function mapping would -% require \cs{@@_to_other:n}, quadratic in the string length. To deal +% require \cs{__kernel_str_to_other:n}, quadratic in the string length. To deal % with spaces in that case, \cs{@@_map_function:w} replaces the % following space by a braced space and a further call to itself. % These are received by \cs{@@_map_function:Nn}, which passes @@ -1317,9 +1243,9 @@ { \exp_after:wN \@@_map_function:w \exp_after:wN \@@_map_function:Nn \exp_after:wN #2 - \etex_detokenize:D {#1} + \__kernel_tl_to_str:w {#1} \q_recursion_tail ? ~ - \__prg_break_point:Nn \str_map_break: { } + \prg_break_point:Nn \str_map_break: { } } \cs_new:Npn \str_map_function:NN { \exp_args:No \str_map_function:nN } @@ -1335,24 +1261,25 @@ \cs_generate_variant:Nn \str_map_function:NN { c } \cs_new_protected:Npn \str_map_inline:nn #1#2 { - \int_gincr:N \g__prg_map_int + \int_gincr:N \g__kernel_prg_map_int \cs_gset_protected:cpn - { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2} + { @@_map_ \int_use:N \g__kernel_prg_map_int :w } ##1 {#2} \use:x { \exp_not:N \@@_map_inline:NN - \exp_not:c { __prg_map_ \int_use:N \g__prg_map_int :w } - \@@_to_other_fast:n {#1} + \exp_not:c { @@_map_ \int_use:N \g__kernel_prg_map_int :w } + \__kernel_str_to_other_fast:n {#1} } \q_recursion_tail - \__prg_break_point:Nn \str_map_break: { \int_gdecr:N \g__prg_map_int } + \prg_break_point:Nn \str_map_break: + { \int_gdecr:N \g__kernel_prg_map_int } } \cs_new_protected:Npn \str_map_inline:Nn { \exp_args:No \str_map_inline:nn } \cs_generate_variant:Nn \str_map_inline:Nn { c } \cs_new:Npn \@@_map_inline:NN #1#2 { - \__quark_if_recursion_tail_break:NN #2 \str_map_break: + \quark_if_recursion_tail_break:NN #2 \str_map_break: \exp_args:No #1 { \token_to_str:N #2 } \@@_map_inline:NN #1 } @@ -1361,25 +1288,25 @@ \use:x { \exp_not:n { \@@_map_variable:NnN #2 {#3} } - \@@_to_other_fast:n {#1} + \__kernel_str_to_other_fast:n {#1} } \q_recursion_tail - \__prg_break_point:Nn \str_map_break: { } + \prg_break_point:Nn \str_map_break: { } } \cs_new_protected:Npn \str_map_variable:NNn { \exp_args:No \str_map_variable:nNn } \cs_new_protected:Npn \@@_map_variable:NnN #1#2#3 { - \__quark_if_recursion_tail_break:NN #3 \str_map_break: + \quark_if_recursion_tail_break:NN #3 \str_map_break: \str_set:Nn #1 {#3} \use:n {#2} \@@_map_variable:NnN #1 {#2} } \cs_generate_variant:Nn \str_map_variable:NNn { c } \cs_new:Npn \str_map_break: - { \__prg_map_break:Nn \str_map_break: { } } + { \prg_map_break:Nn \str_map_break: { } } \cs_new:Npn \str_map_break:n - { \__prg_map_break:Nn \str_map_break: } + { \prg_map_break:Nn \str_map_break: } % \end{macrocode} % \end{macro} % \end{macro} @@ -1394,7 +1321,7 @@ % % \subsection{Accessing specific characters in a string} % -% \begin{macro}[EXP]{\@@_to_other:n} +% \begin{macro}[EXP]{\__kernel_str_to_other:n} % \begin{macro}[EXP]{\@@_to_other_loop:w, \@@_to_other_end:w} % First apply \cs{tl_to_str:n}, then replace all spaces by % \enquote{other} spaces, $8$ at a time, storing the converted part of @@ -1405,7 +1332,7 @@ % the result between \cs{q_mark} and the first |A| (well, there is % also the need to remove a space). % \begin{macrocode} -\cs_new:Npn \@@_to_other:n #1 +\cs_new:Npn \__kernel_str_to_other:n #1 { \exp_after:wN \@@_to_other_loop:w \tl_to_str:n {#1} ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop @@ -1432,13 +1359,13 @@ % \end{macro} % \end{macro} % -% \begin{macro}[rEXP]{\@@_to_other_fast:n} -% \begin{macro}[rEXP]{\@@_to_other_fast_loop:w, \@@_to_other_fast_end:w} -% The difference with \cs{@@_to_other:n} is that the converted part is +% \begin{macro}[rEXP]{\__kernel_str_to_other_fast:n} +% \begin{macro}[rEXP]{\__kernel_str_to_other_fast_loop:w, \@@_to_other_fast_end:w} +% The difference with \cs{__kernel_str_to_other:n} is that the converted part is % left in the input stream, making these commands only % restricted-expandable. % \begin{macrocode} -\cs_new:Npn \@@_to_other_fast:n #1 +\cs_new:Npn \__kernel_str_to_other_fast:n #1 { \exp_after:wN \@@_to_other_fast_loop:w \tl_to_str:n {#1} ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_stop @@ -1491,17 +1418,16 @@ \exp_args:Nf \tl_to_str:n { \exp_args:Nf \@@_item:nn - { \@@_to_other:n {#1} } {#2} + { \__kernel_str_to_other:n {#1} } {#2} } } \cs_new:Npn \str_item_ignore_spaces:nn #1 { \exp_args:No \@@_item:nn { \tl_to_str:n {#1} } } -\__kernel_patch_args:nNNpn { {#1} { \__int_eval:n {#2} } } \cs_new:Npn \@@_item:nn #1#2 { \exp_after:wN \@@_item:w - \__int_value:w \__int_eval:w #2 \exp_after:wN ; - \__int_value:w \@@_count:n {#1} ; + \int_value:w \int_eval:n {#2} \exp_after:wN ; + \int_value:w \@@_count:n {#1} ; #1 \q_stop } \cs_new:Npn \@@_item:w #1; #2; @@ -1513,7 +1439,7 @@ { \exp_after:wN \use_i_delimit_by_q_stop:nw \exp:w \exp_after:wN \@@_skip_exp_end:w - \__int_value:w \__int_eval:w #1 + #2 ; + \int_value:w \int_eval:n { #1 + #2 } ; } } { @@ -1552,12 +1478,15 @@ \exp_after:wN \@@_skip_loop:wNNNNNNNN \else: \exp_after:wN \@@_skip_end:w - \__int_value:w \__int_eval:w + \int_value:w \int_eval:w \fi: #1 ; } \cs_new:Npn \@@_skip_loop:wNNNNNNNN #1; #2#3#4#5#6#7#8#9 - { \exp_after:wN \@@_skip_exp_end:w \__int_value:w \__int_eval:w #1 - 8 ; } + { + \exp_after:wN \@@_skip_exp_end:w + \int_value:w \int_eval:n { #1 - 8 } ; + } \cs_new:Npn \@@_skip_end:w #1 ; { \exp_after:wN \@@_skip_end:NNNNNNNN @@ -1588,19 +1517,17 @@ \exp_args:Nf \tl_to_str:n { \exp_args:Nf \@@_range:nnn - { \@@_to_other:n {#1} } {#2} {#3} + { \__kernel_str_to_other:n {#1} } {#2} {#3} } } \cs_new:Npn \str_range_ignore_spaces:nnn #1 { \exp_args:No \@@_range:nnn { \tl_to_str:n {#1} } } -\__kernel_patch_args:nNNpn - { {#1} { \__int_eval:n {#2} } { \__int_eval:n {#3} } } \cs_new:Npn \@@_range:nnn #1#2#3 { \exp_after:wN \@@_range:w - \__int_value:w \@@_count:n {#1} \exp_after:wN ; - \__int_value:w \__int_eval:w #2 - 1 \exp_after:wN ; - \__int_value:w \__int_eval:w #3 ; + \int_value:w \@@_count:n {#1} \exp_after:wN ; + \int_value:w \int_eval:n { (#2) - 1 } \exp_after:wN ; + \int_value:w \int_eval:n {#3} ; #1 \q_stop } \cs_new:Npn \@@_range:w #1; #2; #3; @@ -1612,7 +1539,7 @@ \cs_new:Npn \@@_range:nnw #1#2 { \exp_after:wN \@@_collect_delimit_by_q_stop:w - \__int_value:w \__int_eval:w #2 - #1 \exp_after:wN ; + \int_value:w \int_eval:n { #2 - #1 } \exp_after:wN ; \exp:w \@@_skip_exp_end:w #1 ; } % \end{macrocode} @@ -1678,14 +1605,15 @@ \cs_new:Npn \@@_collect_loop:wnNNNNNNN #1; #2 #3#4#5#6#7#8#9 { \exp_after:wN \@@_collect_loop:wn - \__int_value:w \__int_eval:w #1 - 7 ; + \int_value:w \int_eval:n { #1 - 7 } ; { #2 #3#4#5#6#7#8#9 } } \cs_new:Npn \@@_collect_end:wn #1 ; { \exp_after:wN \@@_collect_end:nnnnnnnnw - \if_case:w \if_int_compare:w #1 > 0 \exp_stop_f: #1 \else: 0 \fi: \exp_stop_f: - \or: \or: \or: \or: \or: \or: \fi: + \if_case:w \if_int_compare:w #1 > 0 \exp_stop_f: + #1 \else: 0 \fi: \exp_stop_f: + \or: \or: \or: \or: \or: \or: \fi: } \cs_new:Npn \@@_collect_end:nnnnnnnnw #1#2#3#4#5#6#7#8 #9 \q_stop { #1#2#3#4#5#6#7#8 } @@ -1733,7 +1661,7 @@ % \begin{macro}[EXP]{\@@_count:n} % \begin{macro}[EXP]{\@@_count_aux:n, \@@_count_loop:NNNNNNNNN} % To count characters in a string we could first escape all spaces -% using \cs{@@_to_other:n}, then pass the result to \cs{tl_count:n}. +% using \cs{__kernel_str_to_other:n}, then pass the result to \cs{tl_count:n}. % However, the escaping step would be quadratic in the number of % characters in the string, and we can do better. Namely, sum the % number of spaces (\cs{str_count_spaces:n}) and the result of @@ -1881,8 +1809,6 @@ % \begin{macro}[EXP]{\@@_change_case_loop:nw} % \begin{macro}[EXP]{\@@_change_case_space:n} % \begin{macro}[EXP]{\@@_change_case_char:nN} -% \begin{macro} -% {\@@_lookup_lower:N, \@@_lookup_upper:N, \@@_lookup_fold:N} % Case changing for programmatic reasons is done by first detokenizing % input then doing a simple loop that only has to worry about spaces % and everything else. The output is detokenized to allow data sharing @@ -1907,7 +1833,8 @@ \cs_new:Npn \@@_change_case_output:nw #1#2 \@@_change_case_result:n #3 { #2 \@@_change_case_result:n { #3 #1 } } \cs_generate_variant:Nn \@@_change_case_output:nw { f } -\cs_new:Npn \@@_change_case_end:wn #1 \@@_change_case_result:n #2 { #2 } +\cs_new:Npn \@@_change_case_end:wn #1 \@@_change_case_result:n #2 + { \tl_to_str:n {#2} } \cs_new:Npn \@@_change_case_loop:nw #1#2 \q_recursion_stop { \tl_if_head_is_space:nTF {#2} @@ -1915,8 +1842,8 @@ { \@@_change_case_char:nN } {#1} #2 \q_recursion_stop } -\use:x - { \cs_new:Npn \exp_not:N \@@_change_case_space:n ##1 \c_space_tl } +\exp_last_unbraced:NNNNo + \cs_new:Npn \@@_change_case_space:n #1 \c_space_tl { \@@_change_case_output:nw { ~ } \@@_change_case_loop:nw {#1} @@ -1925,41 +1852,11 @@ { \quark_if_recursion_tail_stop_do:Nn #2 { \@@_change_case_end:wn } - \cs_if_exist:cTF { c__unicode_ #1 _ #2 _tl } - { - \@@_change_case_output:fw - { \tl_to_str:c { c__unicode_ #1 _ #2 _tl } } - } - { \@@_change_case_char_aux:nN {#1} #2 } + \@@_change_case_output:fw + { \use:c { char_ #1 _case:N } #2 } \@@_change_case_loop:nw {#1} } % \end{macrocode} -% For Unicode engines there's a look up to see if the current character -% has a valid one-to-one case change mapping. That's not needed for $8$-bit -% engines: as they don't have \cs{utex_char:D} all of the changes they can -% make are hard-coded and so already picked up above. -% \begin{macrocode} -\cs_if_exist:NTF \utex_char:D - { - \cs_new:Npn \@@_change_case_char_aux:nN #1#2 - { - \int_compare:nNnTF { \use:c { __str_lookup_ #1 :N } #2 } = { 0 } - { \@@_change_case_output:nw {#2} } - { - \@@_change_case_output:fw - { \utex_char:D \use:c { __str_lookup_ #1 :N } #2 ~ } - } - } - \cs_new_protected:Npn \@@_lookup_lower:N #1 { \tex_lccode:D `#1 } - \cs_new_protected:Npn \@@_lookup_upper:N #1 { \tex_uccode:D `#1 } - \cs_new_eq:NN \@@_lookup_fold:N \@@_lookup_lower:N - } - { - \cs_new:Npn \@@_change_case_char_aux:nN #1#2 - { \@@_change_case_output:nw {#2} } - } -% \end{macrocode} -% \end{macro} % \end{macro} % \end{macro} % \end{macro} @@ -2024,213 +1921,6 @@ % \end{macrocode} % \end{macro} % -% \subsection{Unicode data for case changing} -% -% \begin{macrocode} -%<@@=unicode> -% \end{macrocode} -% -% Case changing both for strings and \enquote{text} requires data from -% the Unicode Consortium. Some of this is build in to the format (as -% \tn{lccode} and \tn{uccode} values) but this covers only the simple -% one-to-one situations and does not fully handle for example case folding. -% -% The data required for cross-module manipulations is loaded here: currently -% this means for |str| and |tl| functions. As such, the prefix used is not -% |str| but rather |unicode|. For performance (as the entire data set must -% be read during each run) and as this code comes somewhat early in the -% load process, there is quite a bit of low-level code here. -% -% As only the data needs to remain at the end of this process, everything -% is set up inside a group. -% \begin{macrocode} -\group_begin: -% \end{macrocode} -% A read stream is needed. The I/O module is not yet in place \emph{and} -% we do not want to use up a stream. We therefore use a known free one in -% format mode or look for the next free one in package mode (covers plain, -% \LaTeXe{} and Con\TeX{}t MkII and MkIV). -% \begin{macrocode} -%<*initex> - \tex_chardef:D \g_@@_data_ior = 0 \scan_stop: -%</initex> -%<*package> - \tex_chardef:D \g_@@_data_ior - \etex_numexpr:D - \cs_if_exist:NTF \lastallocatedread - { \lastallocatedread } - { - \cs_if_exist:NTF \c_syst_last_allocated_read - { \c_syst_last_allocated_read } - { \tex_count:D 16 ~ } - } - + 1 - \scan_stop: -%</package> -% \end{macrocode} -% Set up to read each file. As they use C-style comments, there is a need to -% deal with |#|. At the same time, spaces are important so they need to be -% picked up as they are important. Beyond that, the current category code -% scheme works fine. With no I/O loop available, hard-code one that works -% quickly. -% \begin{macrocode} - \cs_set_protected:Npn \@@_map_inline:n #1 - { - \group_begin: - \tex_catcode:D `\# = 12 \scan_stop: - \tex_catcode:D `\ = 10 \scan_stop: - \tex_openin:D \g_@@_data_ior = #1 \scan_stop: - \cs_if_exist:NT \utex_char:D - { \@@_map_loop: } - \tex_closein:D \g_@@_data_ior - \group_end: - } - \cs_set_protected:Npn \@@_map_loop: - { - \tex_ifeof:D \g_@@_data_ior - \exp_after:wN \use_none:n - \else: - \exp_after:wN \use:n - \fi: - { - \tex_read:D \g_@@_data_ior to \l_@@_tmp_tl - \if_meaning:w \c_empty_tl \l_@@_tmp_tl - \else: - \exp_after:wN \@@_parse:w \l_@@_tmp_tl \q_stop - \fi: - \@@_map_loop: - } - } -% \end{macrocode} -% The lead-off parser for each line is common for all of the files. If -% the line starts with a |#| it's a comment. There's one special comment -% line to look out for in \texttt{SpecialCasing.txt} as we want to ignore -% everything after it. As this line does not appear in any other sources -% and the test is quite quick (there are relatively few comment lines), it -% can be present in all of the passes. -% \begin{macrocode} - \cs_set_protected:Npn \@@_parse:w #1#2 \q_stop - { - \reverse_if:N \if:w \c_hash_str #1 - \@@_parse_auxi:w #1#2 \q_stop - \else: - \if_int_compare:w \__str_if_eq_x:nn - { \exp_not:n {#2} } { ~Conditional~Mappings~ } = 0 \exp_stop_f: - \cs_set_protected:Npn \@@_parse:w ##1 \q_stop { } - \fi: - \fi: - } -% \end{macrocode} -% Storing each exception is always done in the same way: create a constant -% token list which expands to exactly the mapping. These have the -% category codes \enquote{now} (so should be letters) but are later detokenized -% for string use. -% \begin{macrocode} - \cs_set_protected:Npn \@@_store:nnnnn #1#2#3#4#5 - { - \tl_const:cx { c_@@_ #2 _ \utex_char:D "#1 _tl } - { - \utex_char:D "#3 ~ - \utex_char:D "#4 ~ - \tl_if_blank:nF {#5} - { \utex_char:D "#5 } - } - } -% \end{macrocode} -% Parse the main Unicode data file for title case exceptions (the one-to-one -% lower and upper case mappings it contains are all be covered by the \TeX{} -% data). -% \begin{macrocode} - \cs_set_protected:Npn \@@_parse_auxi:w - #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ; - { \@@_parse_auxii:w #1 ; } - \cs_set_protected:Npn \@@_parse_auxii:w - #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 \q_stop - { - \tl_if_blank:nF {#7} - { - \if_int_compare:w \__str_if_eq_x:nn { #5 ~ } {#7} = 0 \exp_stop_f: - \else: - \tl_const:cx - { c_@@_mixed_ \utex_char:D "#1 _tl } - { \utex_char:D "#7 } - \fi: - } - } - \@@_map_inline:n { UnicodeData.txt } -% \end{macrocode} -% The set up for case folding is in two parts. For the basic (core) mappings, -% folding is the same as lower casing in most positions so only store -% the differences. For the more complex foldings, always store the result, -% splitting up the two or three code points in the input as required. -% \begin{macrocode} - \cs_set_protected:Npn \@@_parse_auxi:w #1 ;~ #2 ;~ #3 ; #4 \q_stop - { - \if_int_compare:w \__str_if_eq_x:nn {#2} { C } = 0 \exp_stop_f: - \if_int_compare:w \tex_lccode:D "#1 = "#3 \scan_stop: - \else: - \tl_const:cx - { c_@@_fold_ \utex_char:D "#1 _tl } - { \utex_char:D "#3 ~ } - \fi: - \else: - \if_int_compare:w \__str_if_eq_x:nn {#2} { F } = 0 \exp_stop_f: - \@@_parse_auxii:w #1 ~ #3 ~ \q_stop - \fi: - \fi: - } - \cs_set_protected:Npn \@@_parse_auxii:w #1 ~ #2 ~ #3 ~ #4 \q_stop - { \@@_store:nnnnn {#1} { fold } {#2} {#3} {#4} } - \@@_map_inline:n { CaseFolding.txt } -% \end{macrocode} -% For upper and lower casing special situations, there is a bit more to -% do as we also have title casing to consider. -% \begin{macrocode} - \cs_set_protected:Npn \@@_parse_auxi:w #1 ;~ #2 ;~ #3 ;~ #4 ; #5 \q_stop - { - \use:n { \@@_parse_auxii:w #1 ~ lower ~ #2 ~ } ~ \q_stop - \use:n { \@@_parse_auxii:w #1 ~ upper ~ #4 ~ } ~ \q_stop - \if_int_compare:w \__str_if_eq_x:nn {#3} {#4} = 0 \exp_stop_f: - \else: - \use:n { \@@_parse_auxii:w #1 ~ mixed ~ #3 ~ } ~ \q_stop - \fi: - } - \cs_set_protected:Npn \@@_parse_auxii:w #1 ~ #2 ~ #3 ~ #4 ~ #5 \q_stop - { - \tl_if_empty:nF {#4} - { \@@_store:nnnnn {#1} {#2} {#3} {#4} {#5} } - } - \@@_map_inline:n { SpecialCasing.txt } -% \end{macrocode} -% For the $8$-bit engines, the above does nothing but there is some set -% up needed. There is no expandable character generator primitive so some -% alternative is needed. As we've not used up hash space for the above, we -% can go for the fast approach here of one name per letter. Keeping folding -% and lower casing separate makes the use later a bit easier. -% \begin{macrocode} - \cs_if_exist:NF \utex_char:D - { - \cs_set_protected:Npn \@@_tmp:NN #1#2 - { - \if_meaning:w \q_recursion_tail #2 - \exp_after:wN \use_none_delimit_by_q_recursion_stop:w - \fi: - \tl_const:cn { c_@@_fold_ #1 _tl } {#2} - \tl_const:cn { c_@@_lower_ #1 _tl } {#2} - \tl_const:cn { c_@@_upper_ #2 _tl } {#1} - \@@_tmp:NN - } - \@@_tmp:NN - AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz - ? \q_recursion_tail \q_recursion_stop - } -% \end{macrocode} -% -% All done: tidy up. -% \begin{macrocode} -\group_end: -% \end{macrocode} -% % \begin{macrocode} %</initex|package> % \end{macrocode} |