summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-01-19 22:49:25 +0000
committerKarl Berry <karl@freefriends.org>2012-01-19 22:49:25 +0000
commit8764984f07460a77b8200111ddb513c8af6c23f3 (patch)
tree61782419c00b217fc7f14919b9e24bbae260274f /Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx
parent17d590a6bcf898806aeec2d7aa57d641a440ca10 (diff)
l3experimental 3209 (19jan12)
git-svn-id: svn://tug.org/texlive/trunk@25158 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx298
1 files changed, 162 insertions, 136 deletions
diff --git a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx
index a33d4909a1a..cddd7349adc 100644
--- a/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx
+++ b/Master/texmf-dist/source/latex/l3experimental/l3str/l3str.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3str.dtx Copyright (C) 2011 The LaTeX3 Project
+%% File: l3str.dtx Copyright (C) 2011-2012 The LaTeX3 Project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{expl3}
-\GetIdInfo$Id: l3str.dtx 3088 2011-12-23 02:00:14Z bruno $
+\GetIdInfo$Id: l3str.dtx 3159 2012-01-09 00:51:58Z bruno $
{L3 Experimental Strings}
%</driver|package>
%<*driver>
@@ -67,6 +67,7 @@
%
% \maketitle
%
+% \newcommand{\hexnum}[1]{\text{\texttt{\char`\"}#1}}
% \begin{documentation}
%
% \LaTeX3 provides a set of functions to manipulate token lists
@@ -106,7 +107,7 @@
% \c_percent_str
% }
% Constant strings, containing a single character, with category code $12$.
-% Other characters can be accessed as \cs{iow_char:N} |\|\meta{character}.
+% Any character can be accessed as \cs{iow_char:N} |\|\meta{character}.
% \end{variable}
%
% \begin{function}[EXP]{\tl_to_str:N, \tl_to_str:n}
@@ -116,6 +117,16 @@
% \end{syntax}
% Converts the \meta{token list} to a \meta{string}, leaving the resulting
% tokens in the input stream.
+% \begin{texnote}
+% The string representation of a token list may depend
+% on the category codes in effect when it is measured,
+% and the value of the \tn{escapechar}: for instance
+% |\tl_to_str:n {\a}| may produce $1$, $2$ or $3$
+% characters depending on the escape character, and
+% the category code of \texttt{a}. This impacts almost
+% all functions in the module, which use \cs{tl_to_str:n}
+% internally.
+% \end{texnote}
% \end{function}
%
% \begin{function}{\str_const:Nn, \str_const:Nx, \str_const:cn, \str_const:cx}
@@ -191,16 +202,16 @@
% (an arbitrary number of hexadecimal digits are read):
% this is mostly useful for Unicode-aware engines.
% \item |\a|, |\e|, |\f|, |\n|, |\r|, |\t| stand for specific characters:
-% \begin{center}
-% \begin{tabular}{cccc}
-% |\a| & |\^^G| & alarm & hex \texttt{07} \\
-% |\e| & |\^^[| & escape & hex \texttt{1B} \\
-% |\f| & |\^^L| & form feed & hex \texttt{0C} \\
-% |\n| & |\^^J| & new line & hex \texttt{0A} \\
-% |\r| & |\^^M| & carriage return & hex \texttt{0D} \\
-% |\t| & |\^^I| & horizontal tab & hex \texttt{09} \\
-% \end{tabular}
-% \end{center}
+% \begin{center}
+% \begin{tabular}{cccc}
+% |\a| & |\^^G| & alarm & hex \texttt{07} \\
+% |\e| & |\^^[| & escape & hex \texttt{1B} \\
+% |\f| & |\^^L| & form feed & hex \texttt{0C} \\
+% |\n| & |\^^J| & new line & hex \texttt{0A} \\
+% |\r| & |\^^M| & carriage return & hex \texttt{0D} \\
+% |\t| & |\^^I| & horizontal tab & hex \texttt{09} \\
+% \end{tabular}
+% \end{center}
% \end{itemize}
% For instance,
% \begin{quote}
@@ -226,13 +237,6 @@
% all characters including spaces are counted.
% The \cs{str_length_ignore_spaces:n} leaves the number of non-space
% characters in the input stream.
-% \begin{texnote}
-% The \cs{str_length:n} of a given token list may depend
-% on the category codes in effect when it is measured,
-% and the value of the \tn{escapechar}: for instance
-% |\str_length:n {\a}| may return $1$, $2$ or $3$ depending
-% on the escape character, and the category code of \texttt{a}.
-% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\str_head:N, \str_head:n, \str_head_ignore_spaces:n}
@@ -262,8 +266,11 @@
% with category codes $12$ and $10$ (for spaces).
% The functions differ in the case where the first character
% is a space: \cs{str_tail:N} and \cs{str_tail:n} will trim
-% only that space, while \cs{str_tail_ignore_spaces:n} trims
+% only that space, while \cs{str_tail_ignore_spaces:n} removes
% the first non-space character and any space before it.
+% If the \meta{token list} is empty (or blank in the case of the
+% \texttt{_ignore_spaces} variant), then nothing is left on the
+% input stream.
% \end{function}
%
% \begin{function}[EXP]{\str_item:Nn, \str_item:nn, \str_item_ignore_spaces:nn}
@@ -432,14 +439,14 @@
% by converting each character in the string \texttt{Hello!}
% to the \textsc{utf-16} encoding, and expressing each byte
% as a pair of hexadecimal digits. Note the presence of a
-% (big-endian) byte order mark \texttt{FEFF}, which can be
+% (big-endian) byte order mark \hexnum{FEFF}, which can be
% avoided by specifying the encoding \texttt{utf16be/hex}.
%
% Parts of the \meta{string} which cannot be converted to bytes
% using the \meta{escaping 1} are silently ignored (including non-byte
% characters which could be present in the string).
% Sequences of bytes which are not valid in the \meta{encoding 1}
-% are converted to the replacement character |"FFFD|, and raise
+% are converted to the replacement character \hexnum{FFFD}, and raise
% an error.
% Characters which cannot be encoded in the \meta{encoding 2}
% are silently ignored.
@@ -478,7 +485,7 @@
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
% If the \meta{token} is a hexdecimal digit (upper case or lower case),
-% its upper-case version is left in the input strem, \emph{followed}
+% its upper-case version is left in the input stream, \emph{followed}
% by the \meta{true code}. Otherwise, the \meta{false code} is left
% in the input stream.
% \begin{texnote}
@@ -552,6 +559,7 @@
% \begin{macrocode}
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\RequirePackage{l3tl-analysis}
% \end{macrocode}
%
% Those string-related functions are defined in \pkg{l3kernel}.
@@ -669,7 +677,7 @@
%
% \begin{variable}{\c_str_replacement_char_int}
% When converting, invalid bytes are replaced by the Unicode
-% replacement character \textsc{u-fffd}.
+% replacement character \hexnum{FFFD}.
% \begin{macrocode}
\int_const:Nn \c_str_replacement_char_int { "FFFD }
% \end{macrocode}
@@ -1431,11 +1439,11 @@
{
\exp_after:wN \str_aux_gmap_internal_result_loop:Nww
\exp_after:wN #1
- \g_str_result_tl \q_mark \q_stop \prg_map_break: ,
+ \g_str_result_tl \s_tl \q_stop \prg_map_break: \s_tl
\prg_break_point:n { }
}
}
-\cs_new_nopar:Npn \str_aux_gmap_internal_result_loop:Nww #1#2\q_mark #3,
+\cs_new_nopar:Npn \str_aux_gmap_internal_result_loop:Nww #1 #2 \s_tl #3 \s_tl
{
\use_none_delimit_by_q_stop:w #3 \q_stop
#1 {#3}
@@ -1982,19 +1990,20 @@
\use_none_delimit_by_q_stop:w #1 \q_stop
\tex_dimen:D "#1 = \l_str_tmpa_int sp \scan_stop:
\tex_skip:D \l_str_tmpa_int = "#1 sp \scan_stop:
- \tex_toks:D \l_str_tmpa_int \exp_after:wN { \int_value:w "FFFD }
+ \tex_toks:D \l_str_tmpa_int \exp_after:wN
+ { \int_use:N \c_str_replacement_char_int }
\tex_advance:D \l_str_tmpa_int \c_one
\str_convert_from_eight_bit_load_missing:n
}
\cs_new:Npn \str_convert_from_eight_bit_aux:N #1
{
- #1 \exp_not:N \q_mark
+ #1 \s_tl
\if_num:w \tex_dimen:D `#1 < \l_str_tmpa_int
\if_num:w \tex_skip:D \tex_dimen:D `#1 = `#1 \exp_stop_f:
\tex_the:D \tex_toks:D \tex_dimen:D
\fi:
\fi:
- \int_value:w `#1 ,
+ \int_value:w `#1 \s_tl
}
% \end{macrocode}
% \end{macro}
@@ -2031,7 +2040,10 @@
}
\cs_new:Npn \str_convert_to_eight_bit_aux:n #1
{
- \if_num:w #1 < "8000 \exp_stop_f:
+ \if_num:w #1 > \c_max_register_int
+ \msg_expandable_kernel_error:nnn
+ { str } { eight-bit-to-byte-overflow } {#1}
+ \else:
\if_num:w \tex_dimen:D #1 < \l_str_tmpa_int
\if_num:w \tex_skip:D \tex_dimen:D #1 = #1 \exp_stop_f:
\tex_the:D \tex_toks:D \tex_dimen:D #1 \exp_stop_f:
@@ -2039,9 +2051,6 @@
\fi:
\fi:
\str_convert_to_eight_bit_aux_ii:n {#1}
- \else:
- \msg_expandable_kernel_error:nnn
- { str } { eight-bit-to-byte-overflow } {#1}
\fi:
}
\cs_new:Npn \str_convert_to_eight_bit_aux_ii:n #1
@@ -2145,7 +2154,7 @@
\cs_new_protected_nopar:Npn \str_convert_from_native:
{ \str_aux_gmap_result:N \str_convert_from_native_aux:N }
\cs_new:Npn \str_convert_from_native_aux:N #1
- { #1 \exp_not:N \q_mark \int_value:w `#1 , }
+ { #1 \s_tl \int_value:w `#1 \s_tl }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -2169,10 +2178,10 @@
\str_aux_convert_to_native:n
{
\exp_after:wN \str_convert_to_native_aux:w
- \l_str_tmpa_tl \q_mark { \q_stop \prg_map_break: } ,
+ \l_str_tmpa_tl \s_tl { \q_stop \prg_map_break: } \s_tl
}
}
-\cs_new_protected_nopar:Npn \str_convert_to_native_aux:w #1\q_mark #2,
+\cs_new_protected_nopar:Npn \str_convert_to_native_aux:w #1 \s_tl #2 \s_tl
{
\use_none_delimit_by_q_stop:w #2 \q_stop
\str_aux_convert_to_native_step:n {#2}
@@ -2294,6 +2303,8 @@
{ Overlong~UTF-8~byte~sequence~for~code~point~#1. }
\msg_kernel_new:nnn { str } { utf8-premature-end }
{ Incomplete~last~UTF-8~character. }
+\msg_kernel_new:nnn { str } { utf8-overflow }
+ { Code~point~#1~too~large~(UTF-8). }
\msg_kernel_new:nnn { str } { utf32-overflow }
{ Code~point~too~large~(UTF-32~`#1'). }
\msg_kernel_new:nnn { str } { utf32-truncated }
@@ -2584,7 +2595,7 @@
% \begin{variable}{\c_str_convert_output_name_not_str}
% For each byte, test whether it should
% be output as is, or be \enquote{hash-encoded}.
-% Roughly, bytes outside the range from |"2A| to |"7E|
+% Roughly, bytes outside the range $[\hexnum{2A},\hexnum{7E}]$
% are hash-encoded. We keep two lists of exceptions:
% characters in \cs{c_str_convert_output_name_not_str}
% are not hash-encoded, and characters in the
@@ -2767,22 +2778,21 @@
% \begin{macro}[aux, rEXP]
% {
% \str_aux_from_utf_viii:N,
-% \str_aux_from_utf_viii:wwNN,
-% \str_aux_from_utf_viii:wNNww
+% \str_aux_from_utf_viii:wwN,
+% \str_aux_from_utf_viii:wNnnwN
% }
% \begin{macro}[aux, rEXP]
% {
-% \str_aux_from_utf_viii_error:w,
-% \str_aux_from_utf_viii_error:NwNN,
+% \str_aux_from_utf_viii_overflow:w ,
% \str_aux_from_utf_viii_error:
% }
-% In the \textsc{utf-8} encoding, bytes in the range $[0,127]$ stand
-% for themselves, bytes in the range $[128,191]$ are continuation bytes,
+% In the \textsc{utf-8} encoding, bytes in the range
+% $[0,\hexnum{7F}]$ stand for themselves, bytes in the range
+% $[\hexnum{80},\hexnum{BF}]$ are continuation bytes,
% and larger bytes must be followed by a number of continuation bytes.
% Documentation to come.
% ^^A todo: refuse "D800 -- "DFFF?
% ^^A todo: document
-% ^^A todo: what error recovery for code points > "10FFFF?
% \begin{macrocode}
\cs_new_protected_nopar:cpn { str_convert_from_utf8: }
{
@@ -2797,7 +2807,7 @@
{
#1
\if_num:w `#1 < "C0 \exp_stop_f:
- \exp_not:N \q_mark
+ \s_tl
\if_num:w `#1 < "80 \exp_stop_f:
\int_value:w `#1
\else:
@@ -2807,71 +2817,73 @@
\fi:
\else:
\if_num:w `#1 < "F5 \exp_stop_f:
- \exp_after:wN \str_aux_from_utf_viii:wwNN
- \int_use:N \int_eval:w `#1 - "C0
+ \exp_after:wN \str_aux_from_utf_viii:wwN
+ \int_value:w \int_eval:n { `#1 - "C0 }
\else:
- \exp_not:N \q_mark
+ \s_tl
\msg_expandable_kernel_error:nnn
{ str } { utf8-invalid-byte } {#1}
\int_use:N \c_str_replacement_char_int
\fi:
\fi:
- ,
- \use_none_delimit_by_q_stop:w
- "80 , "800 , "10000 , "10FFFF ,
- \q_stop
+ \s_tl
+ \use_none_delimit_by_q_stop:w {"80} {"800} {"10000} {"110000} \q_stop
\str_aux_from_utf_viii:N
}
-\cs_new_nopar:Npn \str_aux_from_utf_viii:wwNN #1 , #2 \q_stop #3#4
+\cs_new_nopar:Npn \str_aux_from_utf_viii:wwN
+ #1 \s_tl #2 \str_aux_from_utf_viii:N #3
{
- \use_none:n #4
- \exp_after:wN \str_aux_from_utf_viii:wNNww
- \int_use:N \int_eval:w #1 * "40 + `#4 - "80 ,
- #4
- #2
- \q_stop #3
+ \use_none:n #3
+ \if_num:w \int_eval:w ( `#3 + "20 ) / "40 = \c_three
+ #3
+ \exp_after:wN \str_aux_from_utf_viii:wNnnwN
+ \int_value:w \int_eval:n { #1 * "40 + `#3 - "80 }
+ \else:
+ \s_tl
+ \msg_expandable_kernel_error:nnn
+ { str } { utf8-missing-conti } {#3}
+ \int_use:N \c_str_replacement_char_int
+ \fi:
+ \s_tl
+ #2
+ \str_aux_from_utf_viii:N #3
}
-\cs_new_nopar:Npn \str_aux_from_utf_viii:wNNww #1, #2 #3#4, #5,
+\cs_new_nopar:Npn \str_aux_from_utf_viii:wNnnwN
+ #1 \s_tl #2#3#4 #5 \str_aux_from_utf_viii:N #6
{
- \if_num:w \int_eval:w ( `#2 + \c_thirty_two ) / "40 = \c_three
- \if_num:w #1 < #4 \exp_stop_f:
- \str_aux_from_utf_viii_error:w #1 ,
+ \if_num:w #1 < #4
+ \s_tl
+ \if_num:w #1 < #3 \exp_stop_f:
+ \msg_expandable_kernel_error:nnn
+ { str } { utf8-overlong } {#1}
+ \int_use:N \c_str_replacement_char_int
\else:
- #2
- \if_num:w #1 < #5 \exp_stop_f:
- \exp_not:N \q_mark #1
- \else:
- \exp_after:wN \str_aux_from_utf_viii:wwNN
- \int_use:N \int_eval:w #1 - #5
- \fi:
+ #1
\fi:
\else:
- \exp_after:wN \str_aux_from_utf_viii_error:NwN
- \exp_after:wN #2
+ \if_meaning:w \q_stop #5
+ \str_aux_from_utf_viii_overflow:w #1
+ \fi:
+ \exp_after:wN \str_aux_from_utf_viii:wwN
+ \int_value:w \int_eval:n { #1 - #4 }
\fi:
- , #3#5,
- }
-\cs_new_nopar:Npn \str_aux_from_utf_viii_error:w #1 ,
- {
- \exp_not:N \q_mark
- \msg_expandable_kernel_error:nnn
- { str } { utf8-overlong } {#1}
- \c_str_replacement_char_int
+ \s_tl
+ #2 {#4} #5
+ \str_aux_from_utf_viii:N
}
-\cs_new_nopar:Npn \str_aux_from_utf_viii_error:NwN #1 #2 \q_stop #3
+\cs_new_nopar:Npn \str_aux_from_utf_viii_overflow:w #1 \fi: #2 \fi:
{
- \exp_not:N \q_mark
+ \fi: \fi:
\msg_expandable_kernel_error:nnn
- { str } { utf8-missing-conti } {#1}
- \c_str_replacement_char_int ,
- #3#1
+ { str } { utf8-overflow } {#1}
+ \int_use:N \c_str_replacement_char_int
}
\cs_new_nopar:Npn \str_aux_from_utf_viii_error:
{
- \exp_not:N \q_mark
+ \s_tl
\msg_expandable_kernel_error:nn
{ str } { utf8-premature-end }
- \c_str_replacement_char_int ,
+ \int_use:N \c_str_replacement_char_int \s_tl
\prg_map_break:
}
% \end{macrocode}
@@ -3018,19 +3030,32 @@
% \end{macro}
%
% \begin{macro}[aux, rEXP]{\str_aux_from_utf_xvi:NN}
-% \begin{macro}[aux, rEXP]{\str_aux_from_utf_xvi:wNNN}
-% \begin{macro}[aux, rEXP]{\str_aux_from_utf_xvi_error:wNNw}
+% \begin{macro}[aux, rEXP]{\str_aux_from_utf_xvi:NNwNNN}
% \begin{macro}[aux, rEXP]{\str_aux_from_utf_xvi_end:Nw}
-% \begin{macro}[aux, rEXP]{\str_aux_from_utf_xvi_end:wNNww}
+% \begin{macro}[aux, rEXP]{\str_aux_from_utf_xvi_error:NNw}
+% \begin{macro}[aux, rEXP]{\str_aux_from_utf_xvi_error:NNN}
% When \cs{str_aux_from_utf_xvi:NN} is called, \cs{str_tmp:w}
% is such that |\str_tmp:w #1#2| expands to |`#1| if the string
% is big-endian, and |`#2| if the string is little-endian.
-% If the most significant byte is between |"D8| and |"DB|
-% inclusive, then the pair of bytes is a high surrogate,
-% and we fetch the following pair, which must be a low surrogate,
-% \emph{i.e.}, between |"DC| and |"DF| inclusive.
-% Unpaired surrogates are errors, handled with
-% \cs{str_aux_from_utf_xvi_error:wNNw}.
+% If the code unit (a pair of characters) does not represent
+% a surrogate, the \cs{if_case:w} construction expands to nothing,
+% and we leave in the input stream \meta{characters} \cs{s_tl}
+% \meta{char code} \cs{s_tl}, and move on to the next code unit.
+% When the end is found, we check for the case of an odd-length
+% string (an error) and end the mapping.
+%
+% Surrogates are characterized by a most significant byte in the
+% ranges $[\hexnum{D8},\hexnum{DB}]$ and $[\hexnum{DC},\hexnum{DF}]$,
+% detected by dividing the character code by $4$ (\eTeX{} rounds to
+% nearest, ties away from zero). Here, a trail surrogate is invalid,
+% replaced by the replacement character. Lead surrogates are treated by
+% \cs{str_aux_from_utf_xvi:NNwNNN}, which grabs the next two
+% characters, checks for a premature end, and checks whether
+% the code unit is a trailing surrogate. If it is, leave
+% \meta{characters} \cs{s_tl} \meta{char code} \cs{s_tl} in the
+% input stream and move on to the next code unit. Otherwise, raise
+% an error, and continue parsing, replacing only the first code unit
+% (the leading surrogate) by the replacement character.
% \begin{macrocode}
\cs_new:Npn \str_aux_from_utf_xvi:NN #1#2
{
@@ -3039,60 +3064,63 @@
\fi:
\if_case:w
\int_eval:w ( \str_tmp:w #1#2 - "D6 ) / \c_four \int_eval_end:
- \or: #1#2 \exp_after:wN \str_aux_from_utf_xvi:wNNN
- \or: \exp_after:wN \str_aux_from_utf_xvi_error:wNNw
- \else: #1#2 \exp_not:N \q_mark \int_use:N \int_eval:w
+ \or: \exp_after:wN \str_aux_from_utf_xvi:NNwNNN
+ \or: \exp_after:wN \str_aux_from_utf_xvi_error:NNw
\fi:
- "100 * \str_tmp:w #1#2 + \str_tmp:w #2#1 ,
+ #1#2 \s_tl
+ \int_eval:n { "100 * \str_tmp:w #1#2 + \str_tmp:w #2#1 } \s_tl
\str_aux_from_utf_xvi:NN
}
- \cs_new:Npn \str_aux_from_utf_xvi:wNNN #1, #2#3#4
+ \cs_new:Npn \str_aux_from_utf_xvi:NNwNNN #1#2 \s_tl #3 \s_tl #4#5#6
{
- \if_meaning:w \scan_stop: #4
- \str_aux_from_utf_xvi_end:wNNww #1 , #3
+ \if_meaning:w \scan_stop: #6
+ \str_aux_from_utf_xvi_error:NNN #1#2#5
\fi:
- \if_num:w \int_eval:w ( \str_tmp:w #3#4 - "DA ) / \c_four = \c_one
- #3 #4
- \int_use:N \int_eval:w
- ( #1 - "D800 ) * "400
- + \str_tmp:w #3#4 * "100 + \str_tmp:w #4#3 - "DC00 ,
+ \if_num:w \int_eval:w ( \str_tmp:w #5#6 - "DA ) / \c_four = \c_one
+ #1 #2 #5 #6 \s_tl
+ \int_eval:n
+ {
+ ( "100 * \str_tmp:w #1#2 + \str_tmp:w #2#1 - "D800 ) * "400
+ + "100 * \str_tmp:w #4#5 + \str_tmp:w #5#4 - "DC00
+ }
+ \s_tl
\exp_after:wN \use_i:nnn
\else:
- \str_aux_from_utf_xvi_error:wNNw #1 ,
+ \str_aux_from_utf_xvi_error:NNw #1#2 \s_tl \s_tl
\fi:
- #2#3#4
- }
- \cs_new:Npn \str_aux_from_utf_xvi_error:wNNw #1 \str_tmp:w #2#3 #4,
- {
- \exp_not:N \q_mark
- \msg_expandable_kernel_error:nnn
- { str } { utf16-surrogate } { #2#3 }
- \c_str_replacement_char_int ,
+ #4#5#6
}
\cs_new:Npn \str_aux_from_utf_xvi_end:Nw #1 \fi:
{
\fi:
\if_meaning:w \scan_stop: #1
\else:
- #1 \exp_not:N \q_mark
+ #1 \s_tl
\msg_expandable_kernel_error:nnn
{ str } { utf16-odd } {#1}
- \int_use:N \c_str_replacement_char_int ,
+ \int_use:N \c_str_replacement_char_int \s_tl
\fi:
\prg_map_break:
}
- \cs_new:Npn \str_aux_from_utf_xvi_end:wNNww #1 `#2#3 #4, #5 \fi:
+ \cs_new:Npn \str_aux_from_utf_xvi_error:NNw #1#2 \s_tl #3 \s_tl
{
- \fi:
- \exp_not:N \q_mark
- \if_meaning:w \scan_stop: #5
+ #1 #2 \s_tl
+ \msg_expandable_kernel_error:nnn
+ { str } { utf16-surrogate } { #1#2 }
+ \int_use:N \c_str_replacement_char_int \s_tl
+ }
+ \cs_new:Npn \str_aux_from_utf_xvi_error:NNN #1#2#3
+ {
+ \if_meaning:w \scan_stop: #3
+ #1#2 \s_tl
\msg_expandable_kernel_error:nnn
- { str } { utf16-surrogate } { #2#3 }
+ { str } { utf16-surrogate } { #1#2 }
\else:
+ #1#2#3 \s_tl
\msg_expandable_kernel_error:nnn
- { str } { utf16-odd } { #2#3#5 }
+ { str } { utf16-odd } { #1#2#3 }
\fi:
- \int_use:N \c_str_replacement_char_int ,
+ \int_use:N \c_str_replacement_char_int \s_tl
\prg_map_break:
}
% \end{macrocode}
@@ -3180,7 +3208,7 @@
% \begin{macro}[aux, rEXP]
% {
% \str_aux_from_utf_xxxii:NNNN,
-% \str_aux_from_utf_xxxii_end:ww
+% \str_aux_from_utf_xxxii_end:w
% }
% See the conversion functions from \textsc{utf-16} encodings.
% The \cs{str_aux_from_utf_xxxii:No} auxiliary defines
@@ -3226,7 +3254,7 @@
\if_meaning:w \scan_stop: #4
\exp_after:wN \str_aux_from_utf_xxxii_end:w
\fi:
- #1#2#3#4 \exp_not:N \q_mark
+ #1#2#3#4 \s_tl
\if_num:w \int_eval:w
\str_tmp:w #1#4 * \c_two_hundred_fifty_six
+ \str_tmp:w #2#3
@@ -3235,12 +3263,10 @@
{ str } { utf32-overflow } { #1#2#3#4 }
\int_use:N \c_str_replacement_char_int
\else:
- \int_use:N \int_eval:w
- \str_tmp:w #2#3*"10000
- + \str_tmp:w #3#2 * \c_two_hundred_fifty_six
- + \str_tmp:w #4#1
+ \int_eval:n
+ { \str_tmp:w #2#3*"10000 + \str_tmp:w #3#2*"100 + \str_tmp:w #4#1 }
\fi:
- ,
+ \s_tl
\str_aux_from_utf_xxxii:NNNN
}
\cs_new:Npn \str_aux_from_utf_xxxii_end:w #1 \scan_stop:
@@ -3249,8 +3275,8 @@
{
\msg_expandable_kernel_error:nnn
{ str } { utf32-truncated } { #1 }
- #1 \exp_not:N \q_mark
- \int_use:N \c_str_replacement_char_int ,
+ #1 \s_tl
+ \int_use:N \c_str_replacement_char_int \s_tl
}
\prg_map_break:
}