[latex3-commits] [l3svn] branch master updated: Intergrate l3str into the kernel

noreply at latex-project.org noreply at latex-project.org
Fri Sep 18 10:12:34 CEST 2015


This is an automated email from the git hooks/post-receive script.

joseph pushed a commit to branch master
in repository l3svn.

The following commit(s) were added to refs/heads/master by this push:
       new  7f46ad1   Intergrate l3str into the kernel
7f46ad1 is described below

commit 7f46ad1bfa4a8285b5696b45cd519ec87fd7bebd
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Fri Sep 18 09:09:21 2015 +0100

    Intergrate l3str into the kernel
    
    This commit adds all of the 'experimental' part of l3str to expl3.
    The primary driver here is str variables, but it seemed best to
    take everything.
    
    There are a few adjustments to other places to accommodate this.
    Most notably, this now means loading l3str alone gives an error,
    but only a couple of packages outside of the repo do this. Also
    notice loss of some (old) deprecated functions: as these are in
    l3experimental, no notice is needed.
    
    Further adjustment is likely needed yet. In particular, I will
    probably split up the l3str part inside l3experimental since it
    no longer creates a file "l3str.sty"!
---
 l3experimental/l3str/l3regex.dtx                   |    2 +-
 l3experimental/l3str/l3str-expl.dtx                |  984 ------------------
 l3experimental/l3str/l3str-format.dtx              |   20 +-
 l3experimental/l3str/l3str.ins                     |    3 +-
 l3kernel/expl3.dtx                                 |    4 +
 l3kernel/l3.ins                                    |    1 +
 l3kernel/l3file.dtx                                |   33 +-
 l3kernel/l3oldmodules.dtx                          |    1 +
 l3kernel/l3str.dtx                                 | 1062 ++++++++++++++++++--
 l3kernel/testfiles/m3expl001.luatex.tlg            |  148 ++-
 l3kernel/testfiles/m3expl001.ptex.tlg              |  148 ++-
 l3kernel/testfiles/m3expl001.tlg                   |  148 ++-
 l3kernel/testfiles/m3expl001.uptex.tlg             |  148 ++-
 l3kernel/testfiles/m3expl001.xetex.tlg             |  148 ++-
 l3kernel/testfiles/m3expl003.luatex.tlg            |  148 ++-
 l3kernel/testfiles/m3expl003.ptex.tlg              |  148 ++-
 l3kernel/testfiles/m3expl003.tlg                   |  148 ++-
 l3kernel/testfiles/m3expl003.uptex.tlg             |  148 ++-
 l3kernel/testfiles/m3expl003.xetex.tlg             |  148 ++-
 .../testfiles/m3str003.lvt                         |    0
 .../testfiles/m3str003.tlg                         |    0
 21 files changed, 2400 insertions(+), 1190 deletions(-)

diff --git a/l3experimental/l3str/l3regex.dtx b/l3experimental/l3str/l3regex.dtx
index 65823f2..b7e5154 100644
--- a/l3experimental/l3str/l3regex.dtx
+++ b/l3experimental/l3str/l3regex.dtx
@@ -753,7 +753,7 @@
 %<*package>
 \ProvidesExplPackage
   {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\RequirePackage{l3tl-build, l3tl-analysis, l3flag, l3str, l3str-convert}
+\RequirePackage{l3tl-build, l3tl-analysis, l3flag, l3str-convert}
 %</package>
 %    \end{macrocode}
 %
diff --git a/l3experimental/l3str/l3str-expl.dtx b/l3experimental/l3str/l3str-expl.dtx
deleted file mode 100644
index d1763a0..0000000
--- a/l3experimental/l3str/l3str-expl.dtx
+++ /dev/null
@@ -1,984 +0,0 @@
-% \iffalse meta-comment
-%
-%% File: l3str.dtx Copyright (C) 2011-2015 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
-%% license or (at your option) any later version.  The latest version
-%% of this license is in the file
-%%
-%%    http://www.latex-project.org/lppl.txt
-%%
-%% This file is part of the "l3experimental bundle" (The Work in LPPL)
-%% and all files in that bundle must be distributed together.
-%%
-%% The released version of this bundle is available from CTAN.
-%%
-%% -----------------------------------------------------------------------
-%%
-%% The development version of the bundle can be found at
-%%
-%%    http://www.latex-project.org/svnroot/experimental/trunk/
-%%
-%% for those people who are interested.
-%%
-%%%%%%%%%%%
-%% NOTE: %%
-%%%%%%%%%%%
-%%
-%%   Snapshots taken from the repository represent work in progress and may
-%%   not work or may contain conflicting material!  We therefore ask
-%%   people _not_ to put them into distributions, archives, etc. without
-%%   prior consultation with the LaTeX3 Project.
-%%
-%% -----------------------------------------------------------------------
-%
-%<*driver|package>
-% The version of expl3 required is tested as early as possible, as
-% some really old versions do not define \ProvidesExplPackage.
-\RequirePackage{expl3}[2015/09/11]
-%<package>\@ifpackagelater{expl3}{2015/09/11}
-%<package>  {}
-%<package>  {%
-%<package>    \PackageError{l3str}{Support package l3kernel too old}
-%<package>      {%
-%<package>        Please install an up to date version of l3kernel\MessageBreak
-%<package>        using your TeX package manager or from CTAN.\MessageBreak
-%<package>        \MessageBreak
-%<package>        Loading l3str will abort!%
-%<package>      }%
-%<package>    \endinput
-%<package>  }
-\GetIdInfo$Id$
-  {L3 Experimental strings}
-\def\ExplFileName{l3str}
-%</driver|package>
-%<*driver>
-\documentclass[full]{l3doc}
-\usepackage{amsmath}
-\begin{document}
-  \DocInput{\jobname.dtx}
-\end{document}
-%</driver>
-% \fi
-%
-%
-% \title{^^A
-%   The \textsf{l3str} package: manipulating strings of characters^^A
-%   \thanks{This file describes v\ExplFileVersion,
-%     last revised \ExplFileDate.}^^A
-% }
-%
-% \author{^^A
-%  The \LaTeX3 Project\thanks
-%    {^^A
-%      E-mail:
-%        \href{mailto:latex-team at latex-project.org}
-%          {latex-team at latex-project.org}^^A
-%    }^^A
-% }
-%
-% \date{Released \ExplFileDate}
-%
-% \maketitle
-%
-% \tableofcontents
-%
-% \begin{documentation}
-%
-% \LaTeX3 provides a set of functions to manipulate token lists
-% as strings of characters, ignoring the category codes of those
-% characters.
-%
-% String variables are simply specialised token lists, but by convention
-% should be named with the suffix \texttt{\ldots{}str}.  Such variables
-% should contain characters with category code $12$ (other), except
-% spaces, which have category code $10$ (blank space).  All the
-% functions in this module which accept a token list argument first
-% convert it to a string using \cs{tl_to_str:n} for internal processing,
-% and will not treat a token list or the corresponding string
-% representation differently.
-%
-% Most expandable functions in this module come in three flavours:
-% \begin{itemize}
-%   \item \cs{str_...:N}, which expect a token list or string
-%     variable as their argument;
-%   \item \cs{str_...:n}, taking any token list (or string) as an
-%     argument;
-%   \item \cs{str_..._ignore_spaces:n}, which ignores any space
-%     encountered during the operation: these functions are typically
-%     faster than those which take care of escaping spaces
-%     appropriately.
-% \end{itemize}
-%
-% \section{Building strings}
-%
-% \begin{variable}
-%   {
-%     \c_backslash_str,
-%     \c_left_brace_str,
-%     \c_right_brace_str,
-%     \c_hash_str,
-%     \c_tilde_str,
-%     \c_percent_str
-%   }
-%   Constant strings, containing a single character token, with category
-%   code $12$.  Any character can be accessed as \cs{iow_char:N}
-%   |\|\meta{character}.
-% \end{variable}
-%
-% \begin{function}{\str_new:N, \str_new:c}
-%   \begin{syntax}
-%     \cs{str_new:N} \meta{str~var}
-%   \end{syntax}
-%   Creates a new \meta{str~var} or raises an error if the name is
-%   already taken.  The declaration is global.  The \meta{str~var} will
-%   initially be empty.
-% \end{function}
-%
-% \begin{function}{\str_const:Nn, \str_const:Nx, \str_const:cn, \str_const:cx}
-%   \begin{syntax}
-%     \cs{str_const:Nn} \meta{str~var} \Arg{token list}
-%   \end{syntax}
-%   Creates a new constant \meta{str~var} or raises an error if the name
-%   is already taken.  The value of the \meta{str~var} will be set
-%   globally to the \meta{token list}, converted to a string.
-% \end{function}
-%
-% \begin{function}
-%   {
-%     \str_set:Nn,  \str_set:Nx,  \str_set:cn,  \str_set:cx,
-%     \str_gset:Nn, \str_gset:Nx, \str_gset:cn, \str_gset:cx
-%   }
-%   \begin{syntax}
-%     \cs{str_set:Nn} \meta{str var} \Arg{token list}
-%   \end{syntax}
-%   Converts the \meta{token list} to a \meta{string}, and stores the
-%   result in \meta{str var}.
-% \end{function}
-%
-% \begin{function}
-%   {
-%     \str_put_left:Nn,  \str_put_left:Nx,
-%     \str_put_left:cn,  \str_put_left:cx,
-%     \str_gput_left:Nn, \str_gput_left:Nx,
-%     \str_gput_left:cn, \str_gput_left:cx
-%   }
-%   \begin{syntax}
-%     \cs{str_put_left:Nn} \meta{str var} \Arg{token list}
-%   \end{syntax}
-%   Converts the \meta{token list} to a \meta{string}, and prepends the
-%   result to \meta{str var}.  The current contents of the \meta{str
-%     var} are not automatically converted to a string.
-% \end{function}
-%
-% \begin{function}
-%   {
-%     \str_put_right:Nn,  \str_put_right:Nx,
-%     \str_put_right:cn,  \str_put_right:cx,
-%     \str_gput_right:Nn, \str_gput_right:Nx,
-%     \str_gput_right:cn, \str_gput_right:cx
-%   }
-%   \begin{syntax}
-%     \cs{str_put_right:Nn} \meta{str var} \Arg{token list}
-%   \end{syntax}
-%   Converts the \meta{token list} to a \meta{string}, and appends the
-%   result to \meta{str var}.  The current contents of the \meta{str
-%     var} are not automatically converted to a string.
-% \end{function}
-%
-% \section{Accessing the contents of a string}
-%
-% \begin{function}[EXP]
-%   {\str_count:N, \str_count:n, \str_count_ignore_spaces:n}
-%   \begin{syntax}
-%     \cs{str_count:n} \Arg{token list}
-%   \end{syntax}
-%   Leaves in the input stream the number of characters in the string
-%   representation of \meta{token list}, as an integer denotation.  The
-%   functions differ in their treatment of spaces.  In the case of
-%   \cs{str_count:N} and \cs{str_count:n}, all characters including
-%   spaces are counted.  The \cs{str_count_ignore_spaces:n} function
-%   leaves the number of non-space characters in the input stream.
-% \end{function}
-%
-% \begin{function}[EXP]{\str_count_spaces:N, \str_count_spaces:n}
-%   \begin{syntax}
-%     \cs{str_count_spaces:n} \Arg{token list}
-%   \end{syntax}
-%   Leaves in the input stream the number of space characters in the
-%   string representation of \meta{token list}, as an integer
-%   denotation. Of course, this function has no \texttt{_ignore_spaces}
-%   variant.
-% \end{function}
-%
-% \begin{function}[EXP]{\str_head:N, \str_head:n, \str_head_ignore_spaces:n}
-%   \begin{syntax}
-%     \cs{str_head:n} \Arg{token list}
-%   \end{syntax}
-%   Converts the \meta{token list} into a \meta{string}.  The first
-%   character in the \meta{string} is then left in the input stream,
-%   with category code \enquote{other}.  The functions differ if the
-%   first character is a space: \cs{str_head:N} and \cs{str_head:n}
-%   return a space token with category code~$10$ (blank space), while
-%   the \cs{str_head_ignore_spaces:n} function ignores this space
-%   character and leaves the first non-space character in the input
-%   stream.  If the \meta{string} is empty (or only contains spaces in
-%   the case of the \texttt{_ignore_spaces} function), then nothing is
-%   left on the input stream.
-% \end{function}
-%
-% \begin{function}[EXP]{\str_tail:N, \str_tail:n, \str_tail_ignore_spaces:n}
-%   \begin{syntax}
-%     \cs{str_tail:n} \Arg{token list}
-%   \end{syntax}
-%   Converts the \meta{token list} to a \meta{string}, removes the first
-%   character, and leaves the remaining characters (if any) in the input
-%   stream, 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} 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}
-%   \begin{syntax}
-%     \cs{str_item:nn} \Arg{token list} \Arg{integer expression}
-%   \end{syntax}
-%   Converts the \meta{token list} to a \meta{string}, and leaves in the
-%   input stream the character in position \meta{integer expression} of
-%   the \meta{string}, starting at $1$ for the first (left-most)
-%   character.  In the case of \cs{str_item:Nn} and \cs{str_item:nn},
-%   all characters including spaces are taken into account.  The
-%   \cs{str_item_ignore_spaces:nn} function skips spaces when counting
-%   characters.  If the \meta{integer expression} is negative,
-%   characters are counted from the end of the \meta{string}. Hence,
-%   $-1$ is the right-most character, \emph{etc.}
-% \end{function}
-%
-% \begin{function}[EXP]
-%   {\str_range:Nnn, \str_range:nnn, \str_range_ignore_spaces:nnn}
-%   \begin{syntax}
-%     \cs{str_range:nnn} \Arg{token list} \Arg{start index} \Arg{end index}
-%   \end{syntax}
-%   Converts the \meta{token list} to a \meta{string}, and leaves in the
-%   input stream the characters from the \meta{start index} to the
-%   \meta{end index} inclusive.  Positive \meta{indices} are counted
-%   from the start of the string, $1$~being the first character, and
-%   negative \meta{indices} are counted from the end of the string,
-%   $-1$~being the last character.  If either of \meta{start index} or
-%   \meta{end index} is~$0$, the result is empty.  For instance,
-%   \begin{verbatim}
-%     \iow_term:x { \str_range:nnn { abcdef } { 2 } { 5 } }
-%     \iow_term:x { \str_range:nnn { abcdef } { -4 } { -1 } }
-%     \iow_term:x { \str_range:nnn { abcdef } { -2 } { -1 } }
-%     \iow_term:x { \str_range:nnn { abcdef } { 0 } { -1 } }
-%   \end{verbatim}
-%   will print \texttt{bcd}, \texttt{cdef}, \texttt{ef}, and an empty
-%   line to the terminal.
-% \end{function}
-%
-% \section{Viewing strings}
-%
-% \begin{function}{\str_show:N, \str_show:c, \str_show:n}
-%   \begin{syntax}
-%     \cs{str_show:N} \meta{tl~var}
-%   \end{syntax}
-%   Displays the content of the \meta{str~var} on the terminal.
-% \end{function}
-%
-% \section{Scratch strings}
-%
-% \begin{variable}{\l_tmpa_str, \l_tmpb_str}
-%   Scratch strings for local assignment. These are never used by
-%   the kernel code, and so are safe for use with any \LaTeX3-defined
-%   function. However, they may be overwritten by other non-kernel
-%   code and so should only be used for short-term storage.
-% \end{variable}
-%
-% \begin{variable}{\g_tmpa_str, \g_tmpb_str}
-%   Scratch strings for global assignment. These are never used by
-%   the kernel code, and so are safe for use with any \LaTeX3-defined
-%   function. However, they may be overwritten by other non-kernel
-%   code and so should only be used for short-term storage.
-% \end{variable}
-%
-% \section{Internal \pkg{l3str} functions}
-%
-% \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, but there exist
-%   non-expandable ways to reach linear time.
-% \end{function}
-%
-% \begin{function}[EXP]{\__str_count_unsafe:n}
-%   \begin{syntax}
-%     \cs{__str_count_unsafe: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_unsafe:nnn}
-%   \begin{syntax}
-%     \cs{__str_range_unsafe: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}
-%
-% \section{Possible additions to \pkg{l3str}}
-%
-% Semantically correct copies of some \texttt{tl} functions.
-% \begin{itemize}
-%   \item \cs{c_space_str}
-%   \item \cs{str_clear:N}, \cs{str_gclear:N}, \cs{str_clear_new:N},
-%     \cs{str_gclear_new:N}.
-%   \item \cs{str_concat:NNN}, \cs{str_gconcat:NNN}
-%   \item \cs{str_set_eq:NN}, \cs{str_gset_eq:NN}
-%   \item \cs{str_if_empty:NTF}, \cs{str_if_empty_p:N}
-%   \item \cs{str_if_exist:NTF}, \cs{str_if_exist_p:N}
-%   \item \cs{str_use:N}
-% \end{itemize}
-%
-% Some functions that are not copies of \texttt{tl} functions.
-% \begin{itemize}
-%   \item \cs{str_if_blank:NTF}, \cs{str_if_blank_p:N}.
-%   \item \cs{str_map_inline:Nn}, \cs{str_map_function:NN},
-%     \cs{str_map_variable:NNn}, and \texttt{:n} analogs.
-%   \item Expandable \cs{str_if_in:nnTF}?
-%   \item \cs{str_if_head_eq:nNTF}, \cs{str_if_head_eq_p:nN}
-%   \item \cs{str_if_numeric/decimal/integer:n}, perhaps in \pkg{l3fp}?
-% \end{itemize}
-%
-% \end{documentation}
-%
-% \begin{implementation}
-%
-% \section{\pkg{l3str} implementation}
-%
-%    \begin{macrocode}
-%<*initex|package>
-%    \end{macrocode}
-%
-%    \begin{macrocode}
-%<@@=str>
-%    \end{macrocode}
-%
-%    \begin{macrocode}
-\ProvidesExplPackage
-  {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-%    \end{macrocode}
-%
-% The following string-related functions are currently defined in
-% \pkg{l3kernel}.
-% \begin{itemize}
-%   \item \cs{str_if_eq:nn}[pTF] and variants,
-%   \item \cs{str_if_eq_x_return:on}, \cs{str_if_eq_x_return:nn}
-%   \item \cs{tl_to_str:n}, \cs{tl_to_str:N}, \cs{tl_to_str:c},
-%   \item \cs{token_to_str:N}, \cs{cs_to_str:N}
-%   \item \cs{str_head:n}, \cs{__str_head:w}, (copied here)
-%   \item \cs{str_tail:n}, \cs{__str_tail:w}, (copied here)
-%   \item \cs{__str_count_ignore_spaces} (unchanged)
-%   \item \cs{__str_count_loop:NNNNNNNNN} (unchanged)
-% \end{itemize}
-%
-% \subsection{String assignments}
-%
-% \begin{macro}{\str_new:N, \str_new:c}
-%   A string is simply a token list.
-%    \begin{macrocode}
-\cs_new_eq:NN \str_new:N \tl_new:N
-\cs_generate_variant:Nn \str_new:N { c }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}
-%   {
-%     \str_set:Nn, \str_set:Nx,
-%     \str_set:cn, \str_set:cx,
-%     \str_gset:Nn, \str_gset:Nx,
-%     \str_gset:cn, \str_gset:cx,
-%     \str_const:Nn, \str_const:Nx,
-%     \str_const:cn, \str_const:cx,
-%     \str_put_left:Nn, \str_put_left:Nx,
-%     \str_put_left:cn, \str_put_left:cx,
-%     \str_gput_left:Nn, \str_gput_left:Nx,
-%     \str_gput_left:cn, \str_gput_left:cx,
-%     \str_put_right:Nn, \str_put_right:Nx,
-%     \str_put_right:cn, \str_put_right:cx,
-%     \str_gput_right:Nn, \str_gput_right:Nx,
-%     \str_gput_right:cn, \str_gput_right:cx,
-%   }
-%   Simply convert the token list inputs to \meta{strings}.
-%    \begin{macrocode}
-\tl_map_inline:nn
-  {
-    { set }
-    { gset }
-    { const }
-    { put_left }
-    { gput_left }
-    { put_right }
-    { gput_right }
-  }
-  {
-    \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 }
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \subsection{String variables and constants}
-%
-% \begin{variable}
-%   {
-%     \c_backslash_str,
-%     \c_left_brace_str,
-%     \c_right_brace_str,
-%     \c_hash_str,
-%     \c_tilde_str,
-%     \c_percent_str
-%   }
-%   For all of those strings, use \cs{cs_to_str:N} to get characters with
-%   the correct category code. The conditional for \cs{c_backslash_str}
-%   is needed as while this code is experimental others may also
-%   define the name (see \pkg{xpatch} for example).
-%    \begin{macrocode}
-%<*package>
-\cs_if_exist:NF \c_backslash_str
-  { \str_const:Nx \c_backslash_str { \cs_to_str:N \\ } }
-%</package>
-%<*initex>
-\str_const:Nx \c_backslash_str { \cs_to_str:N \\ }
-%</initex>
-\str_const:Nx \c_left_brace_str  { \cs_to_str:N \{ }
-\str_const:Nx \c_right_brace_str { \cs_to_str:N \} }
-\str_const:Nx \c_hash_str      { \cs_to_str:N \# }
-\str_const:Nx \c_tilde_str     { \cs_to_str:N \~ }
-\str_const:Nx \c_percent_str   { \cs_to_str:N \% }
-%    \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_tmpa_str, \l_tmpb_str, \g_tmpa_str, \g_tmpb_str}
-%   Scratch strings.
-%    \begin{macrocode}
-\str_new:N \l_tmpa_str
-\str_new:N \l_tmpb_str
-\str_new:N \g_tmpa_str
-\str_new:N \g_tmpb_str
-%    \end{macrocode}
-% \end{variable}
-%
-% \subsection{Counting characters}
-%
-% \begin{macro}[EXP]{\str_count_spaces:N, \str_count_spaces:n}
-% \begin{macro}[EXP, aux]{\@@_count_spaces_loop:wwwwwwwww}
-%   To speed up this function, we grab and discard $9$ space-delimited
-%   arguments in each iteration of the loop.  The loop stops when the
-%   last argument is one of the trailing |X|\meta{number}, and that
-%   \meta{number} is added to the sum of $9$ that precedes, to adjust
-%   the result.
-%    \begin{macrocode}
-\cs_new_nopar:Npn \str_count_spaces:N
-  { \exp_args:No \str_count_spaces:n }
-\cs_new:Npn \str_count_spaces:n #1
-  {
-    \int_eval:n
-      {
-        \exp_after:wN \@@_count_spaces_loop:wwwwwwwww
-        \tl_to_str:n {#1} ~
-        X 7 ~ X 6 ~ X 5 ~ X 4 ~ X 3 ~ X 2 ~ X 1 ~ X 0 ~ X -1 ~
-        \q_stop
-      }
-  }
-\cs_new:Npn \@@_count_spaces_loop:wwwwwwwww #1~#2~#3~#4~#5~#6~#7~#8~#9~
-  {
-    \if_meaning:w X #9
-      \use_i_delimit_by_q_stop:nw
-    \fi:
-    \c_nine + \@@_count_spaces_loop:wwwwwwwww
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\str_count:N, \str_count:n, \str_count_ignore_spaces:n}
-% \begin{macro}[EXP, int]{\@@_count_unsafe:n}
-% \begin{macro}[EXP, aux]{\@@_count: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}.
-%   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
-%   \cs{tl_count:n}, which ignores spaces.  Since strings tend to be
-%   longer than token lists, we use specialized functions to count
-%   characters ignoring spaces.  Namely, loop, grabbing $9$ non-space
-%   characters at each step, and end as soon as we reach one of the $9$
-%   trailing items.  The \texttt{_unsafe} variant expects a token list
-%   already converted to category code $12$ characters, and is used by
-%   \cs{str_item:nn} and \cs{str_range:nnn}.
-%    \begin{macrocode}
-\cs_new_nopar:Npn \str_count:N { \exp_args:No \str_count:n }
-\cs_new:Npn \str_count:n #1
-  {
-    \@@_count:n
-      {
-        \str_count_spaces:n {#1}
-        + \exp_after:wN \@@_count_loop:NNNNNNNNN \tl_to_str:n {#1}
-      }
-  }
-\cs_new:Npn \@@_count_unsafe:n #1
-  {
-    \@@_count:n
-      { \@@_count_loop:NNNNNNNNN #1 }
-  }
-\cs_new:Npn \str_count_ignore_spaces:n #1
-  {
-    \@@_count:n
-      { \exp_after:wN \@@_count_loop:NNNNNNNNN \tl_to_str:n {#1} }
-  }
-\cs_new:Npn \@@_count:n #1
-  {
-    \int_eval:n
-      {
-        #1
-        { X \c_eight } { X \c_seven } { X \c_six   }
-        { X \c_five  } { X \c_four  } { X \c_three }
-        { X \c_two   } { X \c_one   } { X \c_zero  }
-        \q_stop
-      }
-  }
-\cs_set:Npn \@@_count_loop:NNNNNNNNN #1#2#3#4#5#6#7#8#9
-  {
-    \if_meaning:w X #9
-      \exp_after:wN \use_none_delimit_by_q_stop:w
-    \fi:
-    \c_nine + \@@_count_loop:NNNNNNNNN
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Head and tail of a string}
-%
-% \begin{macro}[EXP]{\str_head:N, \str_head:n, \str_head_ignore_spaces:n}
-% \begin{macro}[EXP, aux]{\@@_head:w}
-%   The \texttt{_ignore_spaces} variant is almost identical to
-%   \cs{tl_head:n}.  As usual, \cs{str_head:N} expands its argument and
-%   hands it to \cs{str_head:n}.  To circumvent the fact that \TeX{}
-%   skips spaces when grabbing undelimited macro parameters,
-%   \cs{@@_head:w} takes an argument delimited by a space. If |#1|
-%   starts with a non-space character, \cs{use_i_delimit_by_q_stop:nw}
-%   leaves that in the input stream. On the other hand, if |#1| starts
-%   with a space, the \cs{@@_head:w} takes an empty argument, and the
-%   single (initially braced) space in the definition of \cs{@@_head:w}
-%   makes its way to the output. Finally, for an empty argument, the
-%   (braced) empty brace group in the definition of \cs{str_head:n}
-%   gives an empty result after passing through
-%   \cs{use_i_delimit_by_q_stop:nw}.
-%    \begin{macrocode}
-\cs_new_nopar:Npn \str_head:N { \exp_args:No \str_head:n }
-\cs_set:Npn \str_head:n #1
-  {
-    \exp_after:wN \@@_head:w
-    \tl_to_str:n {#1}
-    { { } } ~ \q_stop
-  }
-\cs_set:Npn \@@_head:w #1 ~ %
-  { \use_i_delimit_by_q_stop:nw #1 { ~ } }
-\cs_new:Npn \str_head_ignore_spaces:n #1
-  {
-    \exp_after:wN \use_i_delimit_by_q_stop:nw
-    \tl_to_str:n {#1} { } \q_stop
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\str_tail:N, \str_tail:n, \str_tail_ignore_spaces:n}
-% \begin{macro}[EXP, aux]{\@@_tail_auxi:w, \@@_tail_auxii:w}
-%   Getting the tail is a little bit more convoluted than the head of a
-%   string.  We hit the front of the string with \cs{reverse_if:N}
-%   \cs{if_charcode:w} \cs{scan_stop:}.  This removes the first
-%   character, and necessarily makes the test true, since the character
-%   cannot match \cs{scan_stop:}. The auxiliary function then inserts
-%   the required \cs{fi:} to close the conditional, and leaves the tail
-%   of the string in the input stream.  The details are such that an
-%   empty string has an empty tail (this requires in particular that the
-%   end-marker |X| be unexpandable and not a control sequence).  The
-%   \texttt{_ignore_spaces} is rather simpler: after converting the
-%   input to a string, \cs{@@_tail_auxii:w} removes one undelimited
-%   argument and leaves everything else until an end-marker \cs{q_mark}.
-%   One can check that an empty (or blank) string yields an empty
-%   tail.
-%    \begin{macrocode}
-\cs_new_nopar:Npn \str_tail:N { \exp_args:No \str_tail:n }
-\cs_set:Npn \str_tail:n #1
-  {
-    \exp_after:wN \@@_tail_auxi:w
-    \reverse_if:N \if_charcode:w
-        \scan_stop: \tl_to_str:n {#1} X X \q_stop
-  }
-\cs_set:Npn \@@_tail_auxi:w #1 X #2 \q_stop { \fi: #1 }
-\cs_new:Npn \str_tail_ignore_spaces:n #1
-  {
-    \exp_after:wN \@@_tail_auxii:w
-    \tl_to_str:n {#1} \q_mark \q_mark \q_stop
-  }
-\cs_new:Npn \@@_tail_auxii:w #1 #2 \q_mark #3 \q_stop { #2 }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Accessing specific characters in a string}
-%
-% \begin{macro}[EXP, int]{\@@_to_other:n}
-% \begin{macro}[EXP, aux]{\@@_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
-%   the string between the \cs{q_mark} and \cs{q_stop} markers.  The end
-%   is detected when \cs{@@_to_other_loop:w} finds one of the trailing
-%   |A|, distinguished from any contents of the initial token list by
-%   their category.  Then \cs{@@_to_other_end:w} is called, and finds
-%   the result between \cs{q_mark} and the first |A| (well, there is
-%   also the need to remove a space).
-%    \begin{macrocode}
-\group_begin:
-\char_set_lccode:nn { `\* } { `\  }
-\char_set_lccode:nn { `\A } { `\A }
-\tl_to_lowercase:n
-  {
-    \group_end:
-    \cs_new:Npn \@@_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
-      }
-    \cs_new:Npn \@@_to_other_loop:w
-      #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 \q_stop
-      {
-        \if_meaning:w A #8
-          \@@_to_other_end:w
-        \fi:
-        \@@_to_other_loop:w
-        #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop
-      }
-    \cs_new:Npn \@@_to_other_end:w \fi: #1 \q_mark #2 * A #3 \q_stop
-      { \fi: #2 }
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP, aux]{\@@_skip_exp_end:w}
-% \begin{macro}[EXP, aux]
-%   {\@@_skip_loop:wNNNNNNNN, \@@_skip_end:w, \@@_skip_end:NNNNNNNN}
-%   Removes |max(#1,0)| characters from the input stream, and then
-%   leaves \cs{exp_end:}.  This should be expanded using
-%   \cs{exp:w}.  We remove characters $8$ at a time until
-%   there are at most $8$ to remove.  Then we do a dirty trick: the
-%   \cs{if_case:w} construction leaves between $0$ and $8$ times the
-%   \cs{or:} control sequence, and those \cs{or:} become arguments of
-%   \cs{@@_skip_end:NNNNNNNN}.  If the number of characters to remove
-%   is $6$, say, then there are two \cs{or:} left, and the $8$ arguments
-%   of \cs{@@_skip_end:NNNNNNNN} are the two \cs{or:}, and $6$
-%   characters from the input stream, exactly what we wanted to
-%   remove. Then close the \cs{if_case:w} conditional with \cs{fi:}, and
-%   stop the initial expansion with \cs{exp_end:} (see places where
-%   \cs{@@_skip_exp_end:w} is called).
-%    \begin{macrocode}
-\cs_new:Npn \@@_skip_exp_end:w #1;
-  {
-    \if_int_compare:w #1 > \c_eight
-      \exp_after:wN \@@_skip_loop:wNNNNNNNN
-    \else:
-      \exp_after:wN \@@_skip_end:w
-      \int_use:N \__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_use:N \__int_eval:w #1 - \c_eight ; }
-\cs_new:Npn \@@_skip_end:w #1 ;
-  {
-    \exp_after:wN \@@_skip_end:NNNNNNNN
-    \if_case:w #1 \exp_stop_f: \or: \or: \or: \or: \or: \or: \or: \or:
-  }
-\cs_new:Npn \@@_skip_end:NNNNNNNN #1#2#3#4#5#6#7#8 { \fi: \exp_end: }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP, aux]{\@@_collect_delimit_by_q_stop:w}
-% \begin{macro}[EXP, aux]
-%   {
-%     \@@_collect_loop:wn, \@@_collect_loop:wnNNNNNNN,
-%     \@@_collect_end:wn, \@@_collect_end:nnnnnnnnw
-%   }
-%   Collects |max(#1,0)| characters, and removes everything else until
-%   \cs{q_stop}. This is somewhat similar to \cs{@@_skip_exp_end:w}, but
-%   accepts integer expression arguments.  This time we can only grab
-%   $7$ characters at a time.  At the end, we use an \cs{if_case:w}
-%   trick again, so that the $8$ first arguments of
-%   \cs{@@_collect_end:nnnnnnnnw} are some \cs{or:}, followed by an
-%   \cs{fi:}, followed by |#1| characters from the input stream. Simply
-%   leaving this in the input stream will close the conditional properly
-%   and the \cs{or:} disappear.
-%    \begin{macrocode}
-\cs_new:Npn \@@_collect_delimit_by_q_stop:w #1;
-  { \@@_collect_loop:wn #1 ; { } }
-\cs_new:Npn \@@_collect_loop:wn #1 ;
-  {
-    \if_int_compare:w #1 > \c_seven
-      \exp_after:wN \@@_collect_loop:wnNNNNNNN
-    \else:
-      \exp_after:wN \@@_collect_end:wn
-    \fi:
-    #1 ;
-  }
-\cs_new:Npn \@@_collect_loop:wnNNNNNNN #1; #2 #3#4#5#6#7#8#9
-  {
-    \exp_after:wN \@@_collect_loop:wn
-    \int_use:N \__int_eval:w #1 - \c_seven ;
-    { #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 > \c_zero #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 }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\str_item:Nn, \str_item:nn, \str_item_ignore_spaces:nn}
-% \begin{macro}[EXP, aux]{\@@_item_unsafe:nn, \@@_item:ww}
-%   The \cs{str_item:nn} hands its argument with spaces escaped to
-%   \cs{@@_item_unsafe:nn}, and makes sure to turn the result back into
-%   a proper string (with category code~$10$ spaces) eventually.  The
-%   \cs{str_item_ignore_spaces:nn} function cheats a little bit in that
-%   it doesn't hand to \cs{@@_item_unsafe:nn} an \enquote{other string}.
-%   This is safe, as everything else is done with undelimited arguments.
-%   Then evaluate the \meta{index} argument~|#2| and count characters in
-%   the string, passing those two numbers to \cs{@@_item:ww} for further
-%   analysis.  If the \meta{index} is negative, shift by |#2|, and
-%   remove that number of characters before returning the next item in
-%   the input stream (and if |#1| is smaller than $-|#2|$, nothing is
-%   returned).  If the \meta{index} is positive, ignore that number
-%   (minus one) of characters before returning the next one.  The shift
-%   by one is obtained by inserting an empty brace group before the
-%   string in that case: that brace group also covers the case where the
-%   \meta{index} is zero.
-%    \begin{macrocode}
-\cs_new_nopar:Npn \str_item:Nn { \exp_args:No \str_item:nn }
-\cs_new:Npn \str_item:nn #1#2
-  {
-    \exp_args:Nf \tl_to_str:n
-      {
-        \exp_args:Nf \@@_item_unsafe:nn
-          { \@@_to_other:n {#1} } {#2}
-      }
-  }
-\cs_new:Npn \str_item_ignore_spaces:nn #1
-  { \exp_args:No \@@_item_unsafe:nn { \tl_to_str:n {#1} } }
-\cs_new:Npn \@@_item_unsafe:nn #1#2
-  {
-    \exp_after:wN \@@_item:ww
-    \int_use:N \__int_eval:w #2 \exp_after:wN ;
-    \__int_value:w \@@_count_unsafe:n {#1} ;
-    #1 \q_stop
-  }
-\cs_new:Npn \@@_item:ww #1; #2;
-  {
-    \int_compare:nNnTF {#1} < \c_zero
-      {
-        \int_compare:nNnTF {#1} < {-#2}
-          { \use_none_delimit_by_q_stop:w }
-          {
-            \exp_after:wN \use_i_delimit_by_q_stop:nw
-            \exp:w \exp_after:wN \@@_skip_exp_end:w
-              \int_use:N \__int_eval:w #1 + #2 ;
-          }
-      }
-      {
-        \int_compare:nNnTF {#1} > {#2}
-          { \use_none_delimit_by_q_stop:w }
-          {
-            \exp_after:wN \use_i_delimit_by_q_stop:nw
-            \exp:w \@@_skip_exp_end:w #1 ; { }
-          }
-      }
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP, aux]{\@@_range_normalize:nn}
-%   This function converts an \meta{index} argument into an explicit
-%   position in the string (a result of $0$ denoting \enquote{out of
-%     bounds}).  Expects two explicit integer arguments: the
-%   \meta{index} |#1| and the string count~|#2|.  If |#1| is negative,
-%   replace it by $|#1| + |#2| + 1$, then limit to the range $[0,
-%   |#2|]$.
-%    \begin{macrocode}
-\cs_new:Npn \@@_range_normalize:nn #1#2
-  {
-    \int_eval:n
-      {
-        \if_int_compare:w #1 < \c_zero
-          \if_int_compare:w #1 < -#2 \exp_stop_f:
-            \c_zero
-          \else:
-            #1 + #2 + \c_one
-          \fi:
-        \else:
-          \if_int_compare:w #1 < #2 \exp_stop_f:
-            #1
-          \else:
-            #2
-          \fi:
-        \fi:
-      }
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP]
-%   {\str_range:Nnn, \str_range:nnn, \str_range_ignore_spaces:nnn}
-% \begin{macro}[EXP, int]{\@@_range_unsafe:nnn}
-% \begin{macro}[EXP, aux]{\@@_range:www, \@@_range:nnw}
-%   Sanitize the string.  Then evaluate the arguments.  At this stage we
-%   also decrement the \meta{start index}, since our goal is to know how
-%   many characters should be removed.  Then limit the range to be
-%   non-negative and at most the length of the string (this avoids
-%   needing to check for the end of the string when grabbing
-%   characters), shifting negative numbers by the appropriate amount.
-%   Afterwards, skip characters, then keep some more, and finally drop
-%   the end of the string.
-%    \begin{macrocode}
-\cs_new_nopar:Npn \str_range:Nnn { \exp_args:No \str_range:nnn }
-\cs_new:Npn \str_range:nnn #1#2#3
-  {
-    \exp_args:Nf \tl_to_str:n
-      {
-        \exp_args:Nf \@@_range_unsafe:nnn
-          { \@@_to_other:n {#1} } {#2} {#3}
-      }
-  }
-\cs_new:Npn \str_range_ignore_spaces:nnn #1
-  { \exp_args:No \@@_range_unsafe:nnn { \tl_to_str:n {#1} } }
-\cs_new:Npn \@@_range_unsafe:nnn #1#2#3
-  {
-    \exp_after:wN \@@_range:www
-    \__int_value:w \@@_count_unsafe:n {#1} \exp_after:wN ;
-    \int_use:N \__int_eval:w #2 - \c_one \exp_after:wN ;
-    \int_use:N \__int_eval:w #3 ;
-    #1 \q_stop
-  }
-\cs_new:Npn \@@_range:www #1; #2; #3;
-  {
-    \exp_args:Nf \@@_range:nnw
-      { \@@_range_normalize:nn {#2} {#1} }
-      { \@@_range_normalize:nn {#3} {#1} }
-  }
-\cs_new:Npn \@@_range:nnw #1#2
-  {
-    \exp_after:wN \@@_collect_delimit_by_q_stop:w
-    \int_use:N \__int_eval:w #2 - #1 \exp_after:wN ;
-    \exp:w \@@_skip_exp_end:w #1 ;
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{String conditionals}
-%
-% \begin{macro}[EXP, pTF]{\str_if_eq:NN}
-% \begin{macro}[EXP, pTF]{\str_if_eq:nn, \str_if_eq_x:nn}
-%   Note that \cs{str_if_eq:NN} is different from
-%   \cs{tl_if_eq:NN} because it needs to ignore category codes.
-%    \begin{macrocode}
-\prg_new_conditional:Npnn \str_if_eq:NN #1#2 { p , TF , T , F }
-  {
-    \if_int_compare:w \__str_if_eq_x:nn { \tl_to_str:N #1 } { \tl_to_str:N #2 }
-      = \c_zero \prg_return_true: \else: \prg_return_false: \fi:
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP, TF]{\str_case:nn, \str_case:on, \str_case_x:nn}
-%   Defined in \pkg{l3basics} at present.
-% \end{macro}
-%
-% \subsection{Viewing strings}
-%
-% \begin{macro}{\str_show:n, \str_show:N, \str_show:c}
-%   Displays a string on the terminal.
-%    \begin{macrocode}
-\cs_new_eq:NN \str_show:n \tl_show:n
-\cs_new_eq:NN \str_show:N \tl_show:N
-\cs_generate_variant:Nn \str_show:N { c }
-%    \end{macrocode}
-% \end{macro}
-%
-% \subsection{Deprecated string functions}
-%
-% Deprecated 2013-01-20 for removal by 2013-04-30
-% \begin{macro}[EXP]
-%   {\str_substr:Nnn, \str_substr:nnn, \str_substr_ignore_spaces:nnn}
-% \begin{macro}[EXP, aux]{\@@_substr:nnn}
-%   These functions used to allow for an empty argument to denote the
-%   start/end of the string.  We reimplement them here by first checking
-%   for an empty argument, then only calling the appropriate version of
-%   the \cs{str_range:nnn} function.
-%    \begin{macrocode}
-\cs_new:Npn \str_substr:Nnn #1 { \@@_substr:nnn { \str_range:Nnn #1 } }
-\cs_new:Npn \str_substr:nnn #1 { \@@_substr:nnn { \str_range:nnn {#1} } }
-\cs_new:Npn \str_substr_ignore_spaces:nnn #1
-  { \@@_substr:nnn { \str_range_ignore_spaces:nnn {#1} } }
-\cs_new:Npn \@@_substr:nnn #1#2#3
-  {
-    \tl_if_empty:nTF {#2}
-      { \tl_if_empty:nTF {#3} { #1 { 1} { -1 } } { #1 { 1} {#3} } }
-      { \tl_if_empty:nTF {#3} { #1 {#2} { -1 } } { #1 {#2} {#3} } }
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% Deprecated 2013-01-20 for removal by 2013-04-30
-% \begin{variable}{\c_lbrace_str, \c_rbrace_str}
-%    \begin{macrocode}
-\cs_new_eq:NN \c_lbrace_str \c_left_brace_str
-\cs_new_eq:NN \c_rbrace_str \c_right_brace_str
-%    \end{macrocode}
-% \end{variable}
-%
-%    \begin{macrocode}
-%</initex|package>
-%    \end{macrocode}
-%
-% \end{implementation}
-%
-% \PrintIndex
diff --git a/l3experimental/l3str/l3str-format.dtx b/l3experimental/l3str/l3str-format.dtx
index 8d26be7..3994fc4 100644
--- a/l3experimental/l3str/l3str-format.dtx
+++ b/l3experimental/l3str/l3str-format.dtx
@@ -355,7 +355,7 @@
     \use:nf { #2 #1 }
       {
         \prg_replicate:nn
-          { \int_max:nn { #3 - \__str_count_unsafe:n { #2 #1 } } { 0 } }
+          { \int_max:nn { #3 - \__str_count:n { #2 #1 } } { 0 } }
           {#4}
       }
   }
@@ -374,7 +374,7 @@
 \cs_new:cpn { @@_align_>:nnnN } #1#2#3#4
   {
     \prg_replicate:nn
-      { \int_max:nn { #3 - \__str_count_unsafe:n { #2 #1 } } { 0 } }
+      { \int_max:nn { #3 - \__str_count:n { #2 #1 } } { 0 } }
       {#4}
     #2 #1
   }
@@ -399,7 +399,7 @@
         \prg_replicate:nn
           {
             \int_max:nn \c_zero
-              { #3 - \__str_count_unsafe:n { #2 #1 } - \c_one }
+              { #3 - \__str_count:n { #2 #1 } - \c_one }
             / \c_two
           }
           {#4}
@@ -409,7 +409,7 @@
         \prg_replicate:nn
           {
             \int_max:nn \c_zero
-              { #3 - \__str_count_unsafe:n { #2 #1 } }
+              { #3 - \__str_count:n { #2 #1 } }
             / \c_two
           }
           {#4}
@@ -433,7 +433,7 @@
     \use:nf {#2}
       {
         \prg_replicate:nn
-          { \int_max:nn { #3 - \__str_count_unsafe:n { #2 #1 } } { 0 } }
+          { \int_max:nn { #3 - \__str_count:n { #2 #1 } } { 0 } }
           {#4}
       }
     #1
@@ -472,9 +472,9 @@
 %   a trailing \cs{s__stop} for later retrieval.  Then check that there
 %   was no \meta{sign}.  The width will be useful later, store it after
 %   \cs{s__stop}.  Afterwards, store the precision, and the function
-%   \cs{__str_range_unsafe:nnn} that will be used to extract the first
+%   \cs{__str_range:nnn} that will be used to extract the first
 %   |#5| characters of the string.
-%   There is a need to use the \enquote{unsafe} function, as otherwise
+%   There is a need to use the internal function, as otherwise
 %   leading spaces would get stripped by |f|-expansion.  Finally, check
 %   that the \meta{style} is |?| or |s|.
 %    \begin{macrocode}
@@ -498,8 +498,8 @@
       }
     \@@_put:nw { {#4} }
     \tl_if_empty:nTF {#5}
-      { \@@_put:nw { \__str_range_unsafe:nnn { {1} {-1} } } }
-      { \@@_put:nw { \__str_range_unsafe:nnn { {1} {#5} } } }
+      { \@@_put:nw { \__str_range:nnn { {1} {-1} } } }
+      { \@@_put:nw { \__str_range:nnn { {1} {#5} } } }
     \token_if_eq_charcode:NNF #6 s
       {
         \token_if_eq_charcode:NNF #6 ?
@@ -891,7 +891,7 @@
   {
     \use:nf
       { #1 . #2 }
-      { \prg_replicate:nn { #4 - \__str_count_unsafe:n {#2} } {0} }
+      { \prg_replicate:nn { #4 - \__str_count:n {#2} } {0} }
   }
 %    \end{macrocode}
 % \end{macro}
diff --git a/l3experimental/l3str/l3str.ins b/l3experimental/l3str/l3str.ins
index 0cb61fe..e69aafe 100644
--- a/l3experimental/l3str/l3str.ins
+++ b/l3experimental/l3str/l3str.ins
@@ -1,6 +1,6 @@
 \iffalse meta-comment
 
-File l3str.ins Copyright (C) 2011, 2013 The LaTeX3 Project
+File l3str.ins Copyright (C) 2011, 2013, 2015 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
@@ -36,7 +36,6 @@ Do not distribute a modified version of this file.
 \keepsilent
 
 \generate{\file{l3flag.sty}   {\from{l3flag.dtx}    {package}}}
-\generate{\file{l3str.sty}    {\from{l3str-expl.dtx}{package}}}
 \generate{\file{l3regex.sty}  {\from{l3regex.dtx}   {package}}}
 \generate{\file{l3str-convert.sty}  {\from{l3str-convert.dtx}  {package}}}
 \generate{\file{l3str-format.sty}   {\from{l3str-format.dtx}   {package}}}
diff --git a/l3kernel/expl3.dtx b/l3kernel/expl3.dtx
index b0dbaa7..54f1f06 100644
--- a/l3kernel/expl3.dtx
+++ b/l3kernel/expl3.dtx
@@ -427,6 +427,10 @@
 %   \item[seq]    sequence: a data-type used to implement lists (with
 %                 access at both ends) and stacks;
 %   \item[skip]   \enquote{rubber} lengths;
+%   \item[str]    \TeX{} strings: a special case of |tl| in which all
+%                 characters have category \enquote{other} (catcode~$12$),
+%                 other than spaces which are category \enquote{space}
+%                 (catcode~$10$);
 %   \item[tl]     \enquote{token list variables}: placeholders for token lists.
 % \end{description}
 % When the \meta{type} and \meta{module} are identical (as often happens in
diff --git a/l3kernel/l3.ins b/l3kernel/l3.ins
index 2876e89..20063fa 100644
--- a/l3kernel/l3.ins
+++ b/l3kernel/l3.ins
@@ -119,6 +119,7 @@ Do not distribute a modified version of this file.
 \generate{\file{l3quark.sty}      {\from{l3oldmodules.dtx}       {l3quark,oldmodules}}}
 \generate{\file{l3seq.sty}        {\from{l3oldmodules.dtx}       {l3seq,oldmodules}}}
 \generate{\file{l3skip.sty}       {\from{l3oldmodules.dtx}       {l3skip,oldmodules}}}
+\generate{\file{l3str.sty}        {\from{l3oldmodules.dtx}       {l3str,oldmodules}}}
 \generate{\file{l3tl.sty}         {\from{l3oldmodules.dtx}       {l3tl,oldmodules}}}
 \generate{\file{l3token.sty}      {\from{l3oldmodules.dtx}       {l3token,oldmodules}}}
 
diff --git a/l3kernel/l3file.dtx b/l3kernel/l3file.dtx
index 8d79064..3abe170 100644
--- a/l3kernel/l3file.dtx
+++ b/l3kernel/l3file.dtx
@@ -1757,7 +1757,7 @@
 \cs_new_protected_nopar:Npn \@@_wrap_word:
   {
     \int_set:Nn \l_@@_current_word_int
-      { \__str_count_ignore_spaces:N \l_@@_current_word_tl }
+      { \exp_args:No  \str_count_ignore_spaces:n \l_@@_current_word_tl }
     \int_add:Nn \l_@@_current_line_int { \l_@@_current_word_int }
     \int_compare:nNnTF \l_@@_current_line_int < \l_@@_target_count_int
       { \@@_wrap_word_fits: }
@@ -1858,37 +1858,6 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[aux]{\__str_count_ignore_spaces:N}
-% \begin{macro}[aux]{\__str_count_ignore_spaces:n}
-% \begin{macro}[aux]{\__str_count_loop:NNNNNNNNN}
-%   The wrapping code requires to measure the number of character
-%   in each word. This could be done with \cs{tl_count:n}, but
-%   it is ten times faster (literally) to use the code below.
-%    \begin{macrocode}
-\cs_new_nopar:Npn \__str_count_ignore_spaces:N
-  { \exp_args:No \__str_count_ignore_spaces:n }
-\cs_new:Npn \__str_count_ignore_spaces:n #1
-  {
-    \__int_value:w \__int_eval:w
-      \exp_after:wN \__str_count_loop:NNNNNNNNN \tl_to_str:n {#1}
-        { X8 } { X7 } { X6 } { X5 } { X4 } { X3 } { X2 } { X1 } { X0 }
-      \q_stop
-    \__int_eval_end:
-  }
-\cs_new:Npn \__str_count_loop:NNNNNNNNN #1#2#3#4#5#6#7#8#9
-  {
-    \if_catcode:w X #9
-      \exp_after:wN \use_none_delimit_by_q_stop:w
-    \else:
-      9 +
-      \exp_after:wN \__str_count_loop:NNNNNNNNN
-    \fi:
-  }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
 % \subsection{Messages}
 %
 %    \begin{macrocode}
diff --git a/l3kernel/l3oldmodules.dtx b/l3kernel/l3oldmodules.dtx
index 98272b0..1dd7223 100644
--- a/l3kernel/l3oldmodules.dtx
+++ b/l3kernel/l3oldmodules.dtx
@@ -119,6 +119,7 @@
 %<l3quark>{l3quark}
 %<l3seq>{l3seq}
 %<l3skip>{l3skip}
+%<l3str>{l3str}
 %<l3tl>{l3tl}
 %<l3token>{l3token}
 %    \end{macrocode}
diff --git a/l3kernel/l3str.dtx b/l3kernel/l3str.dtx
index b03b046..5b0dea2 100644
--- a/l3kernel/l3str.dtx
+++ b/l3kernel/l3str.dtx
@@ -1,6 +1,6 @@
 % \iffalse meta-comment
 %
-%% File: l3str.dtx Copyright (C) 2014-2015 The LaTeX3 Project
+%% File: l3str.dtx Copyright (C) 2011-2015 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
@@ -79,33 +79,163 @@
 % space characters which have category code $10$ (\enquote{space}). Thus
 % at a technical level, a \TeX{} string is a token list with the appropriate
 % category codes. In this documentation, these will simply be referred to as
-% strings: note that they can be stored in token lists as normal.
+% strings.
 %
-% The functions documented here take literal token lists,
-% convert to strings and then carry out manipulations. Thus they may
-% informally be described as \enquote{ignoring} category code. Note that
-% the functions \cs{cs_to_str:N}, \cs{tl_to_str:n}, \cs{tl_to_str:N} and
+% String variables are simply specialised token lists, but by convention
+% should be named with the suffix \texttt{\ldots{}str}.  Such variables
+% should contain characters with category code $12$ (other), except
+% spaces, which have category code $10$ (blank space).  All the
+% functions in this module which accept a token list argument first
+% convert it to a string using \cs{tl_to_str:n} for internal processing,
+% and will not treat a token list or the corresponding string
+% representation differently.
+%
+% Note that as string variables are a special case of token list variables
+% the coverage of \cs{str_\ldots{}:N} functions is somewhat smaller than
+% \cs{tl_\ldots{}:N}.
+%
+% The functions \cs{cs_to_str:N}, \cs{tl_to_str:n}, \cs{tl_to_str:N} and
 % \cs{token_to_str:N} (and variants) will generate strings from the appropriate
 % input: these are documented in \pkg{l3basics}, \pkg{l3tl} and \pkg{l3token},
 % respectively.
 %
-% \section{The first character from a string}
+% Most expandable functions in this module come in three flavours:
+% \begin{itemize}
+%   \item \cs{str_...:N}, which expect a token list or string
+%     variable as their argument;
+%   \item \cs{str_...:n}, taking any token list (or string) as an
+%     argument;
+%   \item \cs{str_..._ignore_spaces:n}, which ignores any space
+%     encountered during the operation: these functions are typically
+%     faster than those which take care of escaping spaces
+%     appropriately.
+% \end{itemize}
+%
+% \section{Building strings}
 %
-% \begin{function}[added = 2011-08-10, EXP]{\str_head:n, \str_tail:n}
+% \begin{function}[added = 2015-09-18]{\str_new:N, \str_new:c}
 %   \begin{syntax}
-%     \cs{str_head:n} \Arg{token list}
-%     \cs{str_tail:n} \Arg{token list}
+%     \cs{str_new:N} \meta{str~var}
+%   \end{syntax}
+%   Creates a new \meta{str~var} or raises an error if the name is
+%   already taken.  The declaration is global.  The \meta{str~var} will
+%   initially be empty.
+% \end{function}
+%
+% \begin{function}[added = 2015-09-18]
+%   {\str_const:Nn, \str_const:Nx, \str_const:cn, \str_const:cx}
+%   \begin{syntax}
+%     \cs{str_const:Nn} \meta{str~var} \Arg{token list}
+%   \end{syntax}
+%   Creates a new constant \meta{str~var} or raises an error if the name
+%   is already taken.  The value of the \meta{str~var} will be set
+%   globally to the \meta{token list}, converted to a string.
+% \end{function}
+%
+% \begin{function}[added = 2015-09-18]
+%   {\str_clear:N, \str_clear:c, \str_gclear:N, \str_gclear:c}
+%   \begin{syntax}
+%     \cs{str_clear:N} \meta{str~var}
+%   \end{syntax}
+%   Clears the content of the \meta{str~var}.
+% \end{function}
+%
+% \begin{function}[added = 2015-09-18]{\str_clear_new:N, \str_clear_new:c}
+%   \begin{syntax}
+%     \cs{str_clear_new:N} \meta{str~var}
+%   \end{syntax}
+%   Ensures that the \meta{str~var} exists globally by applying
+%   \cs{str_new:N} if necessary, then applies \cs{str_(g)clear:N} to leave
+%   the \meta{str~var} empty.
+% \end{function}
+%
+% \begin{function}[added = 2015-09-18]
+%   {
+%     \str_set_eq:NN,  \str_set_eq:cN,  \str_set_eq:Nc,  \str_set_eq:cc,
+%     \str_gset_eq:NN, \str_gset_eq:cN, \str_gset_eq:Nc, \str_gset_eq:cc
+%   }
+%   \begin{syntax}
+%     \cs{str_set_eq:NN} \meta{str~var_1} \meta{str~var_2}
 %   \end{syntax}
-%   Converts the \meta{token list} into a string, as described for
-%   \cs{tl_to_str:n}. The \cs{str_head:n} function then leaves
-%   the first character of this string in the input stream.
-%   The \cs{str_tail:n} function leaves all characters except
-%   the first in the input stream. The first character may be
-%   a space. If the \meta{token list} argument is entirely empty,
-%   nothing is left in the input stream.
+%   Sets the content of \meta{str~var_1} equal to that of
+%   \meta{str~var_2}.
 % \end{function}
 %
-% \subsection{Tests on strings}
+% \section{Adding data to string variables}
+%
+% \begin{function}[added = 2015-09-18]
+%   {
+%     \str_set:Nn,  \str_set:Nx,  \str_set:cn,  \str_set:cx,
+%     \str_gset:Nn, \str_gset:Nx, \str_gset:cn, \str_gset:cx
+%   }
+%   \begin{syntax}
+%     \cs{str_set:Nn} \meta{str var} \Arg{token list}
+%   \end{syntax}
+%   Converts the \meta{token list} to a \meta{string}, and stores the
+%   result in \meta{str var}.
+% \end{function}
+%
+% \begin{function}[added = 2015-09-18]
+%   {
+%     \str_put_left:Nn,  \str_put_left:Nx,
+%     \str_put_left:cn,  \str_put_left:cx,
+%     \str_gput_left:Nn, \str_gput_left:Nx,
+%     \str_gput_left:cn, \str_gput_left:cx
+%   }
+%   \begin{syntax}
+%     \cs{str_put_left:Nn} \meta{str var} \Arg{token list}
+%   \end{syntax}
+%   Converts the \meta{token list} to a \meta{string}, and prepends the
+%   result to \meta{str var}.  The current contents of the \meta{str
+%     var} are not automatically converted to a string.
+% \end{function}
+%
+% \begin{function}[added = 2015-09-18]
+%   {
+%     \str_put_right:Nn,  \str_put_right:Nx,
+%     \str_put_right:cn,  \str_put_right:cx,
+%     \str_gput_right:Nn, \str_gput_right:Nx,
+%     \str_gput_right:cn, \str_gput_right:cx
+%   }
+%   \begin{syntax}
+%     \cs{str_put_right:Nn} \meta{str var} \Arg{token list}
+%   \end{syntax}
+%   Converts the \meta{token list} to a \meta{string}, and appends the
+%   result to \meta{str var}.  The current contents of the \meta{str
+%     var} are not automatically converted to a string.
+% \end{function}
+%
+% \subsection{String conditionals}
+%
+% \begin{function}[EXP, pTF, added = 2015-09-18]
+%   {\str_if_exist:N, \str_if_exist:c}
+%   \begin{syntax}
+%     \cs{str_if_exist_p:N} \meta{str~var}
+%     \cs{str_if_exist:NTF} \meta{str~var} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests whether the \meta{str~var} is currently defined.  This does not
+%   check that the \meta{str~var} really is a string.
+% \end{function}
+%
+% \begin{function}[EXP,pTF, added = 2015-09-18]
+%   {\str_if_empty:N, \str_if_empty:c}
+%   \begin{syntax}
+%     \cs{sr_if_empty_p:N} \meta{str~var}
+%     \cs{str_if_empty:NTF} \meta{str~var} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Tests if the \meta{string variable} is entirely empty
+%   (\emph{i.e.}~contains no tokens at all).
+% \end{function}
+%
+% \begin{function}[EXP,pTF, added = 2015-09-18]
+%   {\str_if_eq:NN, \str_if_eq:Nc, \str_if_eq:cN, \str_if_eq:cc}
+%   \begin{syntax}
+%     \cs{str_if_eq_p:NN} \meta{str~var_1} \meta{str~var_2}
+%     \cs{str_if_eq:NNTF} \meta{str~var_1} \meta{str~var_2} \Arg{true code} \Arg{false code}
+%   \end{syntax}
+%   Compares the content of two \meta{str variables} and
+%   is logically \texttt{true} if the two contain the same characters.
+% \end{function}
 %
 % \begin{function}[EXP,pTF]
 %   {
@@ -189,6 +319,116 @@
 %   not be used within this string.
 % \end{function}
 %
+% \section{Working with the content of strings}
+%
+% \begin{function}[EXP, added = 2015-09-18]{\str_use:N, \str_use:c}
+%   \begin{syntax}
+%     \cs{str_use:N} \meta{str~var}
+%   \end{syntax}
+%   Recovers the content of a \meta{str~var} and places it
+%   directly in the input stream. An error will be raised if the variable
+%   does not exist or if it is invalid. Note that it is possible to use
+%   a \meta{str directly without an accessor function.
+% \end{function}
+%
+% \begin{function}[EXP, added = 2015-09-18]
+%   {\str_count:N, \str_count:c, \str_count:n, \str_count_ignore_spaces:n}
+%   \begin{syntax}
+%     \cs{str_count:n} \Arg{token list}
+%   \end{syntax}
+%   Leaves in the input stream the number of characters in the string
+%   representation of \meta{token list}, as an integer denotation.  The
+%   functions differ in their treatment of spaces.  In the case of
+%   \cs{str_count:N} and \cs{str_count:n}, all characters including
+%   spaces are counted.  The \cs{str_count_ignore_spaces:n} function
+%   leaves the number of non-space characters in the input stream.
+% \end{function}
+%
+% \begin{function}[EXP, added = 2015-09-18]
+%   {\str_count_spaces:N, \str_count_spaces:c, \str_count_spaces:n}
+%   \begin{syntax}
+%     \cs{str_count_spaces:n} \Arg{token list}
+%   \end{syntax}
+%   Leaves in the input stream the number of space characters in the
+%   string representation of \meta{token list}, as an integer
+%   denotation. Of course, this function has no \texttt{_ignore_spaces}
+%   variant.
+% \end{function}
+%
+% \begin{function}[EXP, added = 2015-09-18]
+%   {\str_head:N, \str_head:c, \str_head:n, \str_head_ignore_spaces:n}
+%   \begin{syntax}
+%     \cs{str_head:n} \Arg{token list}
+%   \end{syntax}
+%   Converts the \meta{token list} into a \meta{string}.  The first
+%   character in the \meta{string} is then left in the input stream,
+%   with category code \enquote{other}.  The functions differ if the
+%   first character is a space: \cs{str_head:N} and \cs{str_head:n}
+%   return a space token with category code~$10$ (blank space), while
+%   the \cs{str_head_ignore_spaces:n} function ignores this space
+%   character and leaves the first non-space character in the input
+%   stream.  If the \meta{string} is empty (or only contains spaces in
+%   the case of the \texttt{_ignore_spaces} function), then nothing is
+%   left on the input stream.
+% \end{function}
+%
+% \begin{function}[EXP, added = 2015-09-18]
+%   {\str_tail:N, \str_tail:c, \str_tail:n, \str_tail_ignore_spaces:n}
+%   \begin{syntax}
+%     \cs{str_tail:n} \Arg{token list}
+%   \end{syntax}
+%   Converts the \meta{token list} to a \meta{string}, removes the first
+%   character, and leaves the remaining characters (if any) in the input
+%   stream, 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} 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, added = 2015-09-18]
+%   {\str_item:Nn, \str_item:nn, \str_item_ignore_spaces:nn}
+%   \begin{syntax}
+%     \cs{str_item:nn} \Arg{token list} \Arg{integer expression}
+%   \end{syntax}
+%   Converts the \meta{token list} to a \meta{string}, and leaves in the
+%   input stream the character in position \meta{integer expression} of
+%   the \meta{string}, starting at $1$ for the first (left-most)
+%   character.  In the case of \cs{str_item:Nn} and \cs{str_item:nn},
+%   all characters including spaces are taken into account.  The
+%   \cs{str_item_ignore_spaces:nn} function skips spaces when counting
+%   characters.  If the \meta{integer expression} is negative,
+%   characters are counted from the end of the \meta{string}. Hence,
+%   $-1$ is the right-most character, \emph{etc.}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2015-09-18]
+%   {
+%     \str_range:Nnn, \str_range:cnn, \str_range:nnn,
+%     \str_range_ignore_spaces:nnn
+%   }
+%   \begin{syntax}
+%     \cs{str_range:nnn} \Arg{token list} \Arg{start index} \Arg{end index}
+%   \end{syntax}
+%   Converts the \meta{token list} to a \meta{string}, and leaves in the
+%   input stream the characters from the \meta{start index} to the
+%   \meta{end index} inclusive.  Positive \meta{indices} are counted
+%   from the start of the string, $1$~being the first character, and
+%   negative \meta{indices} are counted from the end of the string,
+%   $-1$~being the last character.  If either of \meta{start index} or
+%   \meta{end index} is~$0$, the result is empty.  For instance,
+%   \begin{verbatim}
+%     \iow_term:x { \str_range:nnn { abcdef } { 2 } { 5 } }
+%     \iow_term:x { \str_range:nnn { abcdef } { -4 } { -1 } }
+%     \iow_term:x { \str_range:nnn { abcdef } { -2 } { -1 } }
+%     \iow_term:x { \str_range:nnn { abcdef } { 0 } { -1 } }
+%   \end{verbatim}
+%   will print \texttt{bcd}, \texttt{cdef}, \texttt{ef}, and an empty
+%   line to the terminal.
+% \end{function}
+%
 % \section{String manipulation}
 %
 % \begin{function}[rEXP, added = 2015-03-01]
@@ -294,6 +534,51 @@
 %   \end{texnote}
 % \end{function}
 %
+% \section{Viewing strings}
+%
+% \begin{function}[added = 2015-09-18]
+%   {\str_show:N, \str_show:c, \str_show:n}
+%   \begin{syntax}
+%     \cs{str_show:N} \meta{str~var}
+%   \end{syntax}
+%   Displays the content of the \meta{str~var} on the terminal.
+% \end{function}
+%
+% \section{Constant token lists}
+%
+% \begin{variable}
+%   {
+%     \c_ampersand_str,
+%     \c_backslash_str,
+%     \c_left_brace_str,
+%     \c_right_brace_str,
+%     \c_circumflex_str,
+%     \c_colojn_str,
+%     \c_hash_str,
+%     \c_percent_str,
+%     \c_tilde_str,
+%     \c_underscore_str
+%   }
+%   Constant strings, containing a single character token, with category
+%   code $12$.
+% \end{variable}
+%
+% \section{Scratch strings}
+%
+% \begin{variable}{\l_tmpa_str, \l_tmpb_str}
+%   Scratch strings for local assignment. These are never used by
+%   the kernel code, and so are safe for use with any \LaTeX3-defined
+%   function. However, they may be overwritten by other non-kernel
+%   code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}{\g_tmpa_str, \g_tmpb_str}
+%   Scratch strings for global assignment. These are never used by
+%   the kernel code, and so are safe for use with any \LaTeX3-defined
+%   function. However, they may be overwritten by other non-kernel
+%   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}
@@ -317,6 +602,38 @@
 %   of \cs{str_if_eq_x:nn(TF)} 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}[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}
@@ -331,54 +648,113 @@
 %<@@=str>
 %    \end{macrocode}
 %
-% \begin{macro}{\str_head:n, \str_tail:n}
-% \begin{macro}[aux]{\__str_head:w}
-% \begin{macro}[aux]{\__str_tail: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: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 an empty result.
-%
-%   To remove the first character of \cs{tl_to_str:n} |{#1}|,
-%   we test it using \cs{if_charcode:w} \cs{scan_stop:},
-%   always \texttt{false} for characters. If the argument was non-empty,
-%   then \cs{__str_tail:w} returns everything until the first
-%   \texttt{X} (with category code letter, no risk of confusing
-%   with the user input). If the argument was empty, the first
-%   \texttt{X} is taken by \cs{if_charcode:w}, and nothing
-%   is returned. We use \texttt{X} as a \meta{marker}, rather than
-%   a quark because the test \cs{if_charcode:w} \cs{scan_stop:}
-%   \meta{marker} has to be \texttt{false}.
+% \subsection{Creating and setting string variables}
+%
+% \begin{macro}
+%   {
+%     \str_new:N, \str_new:c,
+%     \str_use:N, \str_use:c,
+%     \str_clear:N, \str_clear:c,
+%     \str_gclear:N,\str_gclear:c,
+%     \str_clear_new:N, \str_clear_new:c,
+%     \str_gclear_new:N, \str_gclear_new:c
+%   }
+% \begin{macro}
+%   {
+%     \str_set_eq:NN,  \str_set_eq:cN,  \str_set_eq:Nc,  \str_set_eq:cc,
+%     \str_gset_eq:NN, \str_gset_eq:cN, \str_gset_eq:Nc, \str_gset_eq:cc
+%   }
+%   A string is simply a token list. The full mapping system isn't set up
+%   yet so do things by hand.
 %    \begin{macrocode}
-\cs_new:Npn \str_head:n #1
-  {
-    \exp_after:wN \__str_head:w
-    \tl_to_str:n {#1}
-    { { } } ~ \q_stop
-  }
-\cs_new:Npn \__str_head:w #1 ~ %
-  { \tl_head:w #1 { ~ } }
-\cs_new:Npn \str_tail:n #1
-  {
-    \exp_after:wN \__str_tail:w
-    \reverse_if:N \if_charcode:w
-        \scan_stop: \tl_to_str:n {#1} X X \q_stop
-  }
-\cs_new:Npn \__str_tail:w #1 X #2 \q_stop { \fi: #1 }
+\group_begin:
+  \cs_set_protected:Npn \@@_tmp:n #1
+    {
+      \tl_if_blank:nF {#1}
+        {
+          \cs_new_eq:cc { str_ #1 :N } { tl_ #1 :N }
+          \exp_args:Nc \cs_generate_variant:Nn { str_ #1 :N } { c }
+          \@@_tmp:n
+        }
+    }
+  \@@_tmp:n
+    { new }
+    { use }
+    { clear }
+    { gclear }
+    { clear_new }
+    { gclear_new }
+    { }
+\group_end:
+\cs_new_eq:NN \str_set_eq:NN \tl_set_eq:NN
+\cs_new_eq:NN \str_gset_eq:NN \tl_gset_eq:NN
+\cs_generate_variant:Nn \str_set_eq:NN  { c , Nc , cc }
+\cs_generate_variant:Nn \str_gset_eq:NN { c , Nc , cc }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
+%
+% \begin{macro}
+%   {
+%     \str_set:Nn, \str_set:Nx,
+%     \str_set:cn, \str_set:cx,
+%     \str_gset:Nn, \str_gset:Nx,
+%     \str_gset:cn, \str_gset:cx,
+%     \str_const:Nn, \str_const:Nx,
+%     \str_const:cn, \str_const:cx,
+%     \str_put_left:Nn, \str_put_left:Nx,
+%     \str_put_left:cn, \str_put_left:cx,
+%     \str_gput_left:Nn, \str_gput_left:Nx,
+%     \str_gput_left:cn, \str_gput_left:cx,
+%     \str_put_right:Nn, \str_put_right:Nx,
+%     \str_put_right:cn, \str_put_right:cx,
+%     \str_gput_right:Nn, \str_gput_right:Nx,
+%     \str_gput_right:cn, \str_gput_right:cx,
+%   }
+%   Simply convert the token list inputs to \meta{strings}.
+%    \begin{macrocode}
+\group_begin:
+  \cs_set_protected:Npn \@@_tmp:n #1
+    {
+      \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 }
+          \@@_tmp:n
+        }
+    }
+  \@@_tmp:n
+    { set }
+    { gset }
+    { const }
+    { put_left }
+    { gput_left }
+    { put_right }
+    { gput_right }
+    { }
+\group_end:
+%    \end{macrocode}
 % \end{macro}
 %
 % \subsection{String comparisons}
 %
-% \begin{macro}[int, EXP]{\__str_if_eq_x:nn}
-% \begin{macro}[aux, EXP]{\__str_escape_x:n}
+% \begin{macro}[pTF, EXP]
+%   {
+%     \str_if_empty:N, \str_if_empty:c,
+%     \str_if_exist:N, \str_if_exist:c
+%   }
+%   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 }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_if_eq_x:nn}
+% \begin{macro}[aux, EXP]{\@@_escape_x:n}
 %   String comparisons rely on the primitive \cs{(pdf)strcmp} if available:
 %   \LuaTeX{} does not have it, so emulation is required. As the net result
 %   is that we do not \emph{always} use the primitive, the correct approach
@@ -392,21 +768,21 @@
 %   otherwise will fail as \cs{luatex_luaescapestring:D} does not double
 %   such tokens.
 %    \begin{macrocode}
-\cs_new:Npn \__str_if_eq_x:nn #1#2 { \pdftex_strcmp:D {#1} {#2} }
+\cs_new:Npn \@@_if_eq_x:nn #1#2 { \pdftex_strcmp:D {#1} {#2} }
 \cs_if_exist:NT \luatex_luatexversion:D
    {
-     \cs_set:Npn \__str_if_eq_x:nn #1#2
+     \cs_set:Npn \@@_if_eq_x:nn #1#2
        {
           \luatex_directlua:D
             {
               l3kernel.strcmp
                 (
-                  " \__str_escape_x:n {#1} " ,
-                  " \__str_escape_x:n {#2} "
+                  " \@@_escape_x:n {#1} " ,
+                  " \@@_escape_x:n {#2} "
                 )
             }
        }
-     \cs_new:Npn \__str_escape_x:n #1
+     \cs_new:Npn \@@_escape_x:n #1
        {
          \luatex_luaescapestring:D
            {
@@ -418,16 +794,16 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int, EXP]{\__str_if_eq_x_return:nn}
+% \begin{macro}[int, 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 \__str_if_eq_x_return:nn #1 #2
+\cs_new:Npn \@@_if_eq_x_return:nn #1 #2
   {
-    \if_int_compare:w \__str_if_eq_x:nn {#1} {#2} = \c_zero
+    \if_int_compare:w \@@_if_eq_x:nn {#1} {#2} = \c_zero
       \prg_return_true:
     \else:
       \prg_return_false:
@@ -450,7 +826,7 @@
 \prg_new_conditional:Npnn \str_if_eq:nn #1#2 { p , T , F , TF }
   {
     \if_int_compare:w
-      \__str_if_eq_x:nn { \exp_not:n {#1} } { \exp_not:n {#2} }
+      \@@_if_eq_x:nn { \exp_not:n {#1} } { \exp_not:n {#2} }
       = \c_zero
       \prg_return_true: \else: \prg_return_false: \fi:
   }
@@ -464,13 +840,31 @@
 \cs_generate_variant:Nn \str_if_eq:nnTF { nV , no , VV }
 \prg_new_conditional:Npnn \str_if_eq_x:nn #1#2 { p , T , F , TF }
   {
-    \if_int_compare:w \__str_if_eq_x:nn {#1} {#2} = \c_zero
+    \if_int_compare:w \@@_if_eq_x:nn {#1} {#2} = \c_zero
       \prg_return_true: \else: \prg_return_false: \fi:
   }
 %    \end{macrocode}
 % \end{macro}
 %
 % \begin{macro}[int, EXP]{\@@_if_eq_x_return:nn}
+%   Defined in \pkg{l3basics}.
+% \end{macro}
+%
+% \begin{macro}[EXP, pTF]
+%   {\str_if_eq:NN, \str_if_eq:Nc, \str_if_eq:cN, \str_if_eq:cc}
+%   Note that \cs{str_if_eq:NN} is different from
+%   \cs{tl_if_eq:NN} because it needs to ignore category codes.
+%    \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 }
+      = \c_zero \prg_return_true: \else: \prg_return_false: \fi:
+  }
+\cs_generate_variant:Nn \str_if_eq:NNT  { c , Nc , cc }
+\cs_generate_variant:Nn \str_if_eq:NNF  { c , Nc , cc }
+\cs_generate_variant:Nn \str_if_eq:NNTF { c , Nc , cc }
+\cs_generate_variant:Nn \str_if_eq_p:NN { c , Nc , cc }
+%    \end{macrocode}
 % \end{macro}
 %
 % \begin{macro}[EXP]
@@ -550,6 +944,442 @@
 % \end{macro}
 % \end{macro}
 %
+% \subsection{Accessing specific characters in a string}
+%
+% \begin{macro}[EXP, int]{\@@_to_other:n}
+% \begin{macro}[EXP, aux]{\@@_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
+%   the string between the \cs{q_mark} and \cs{q_stop} markers.  The end
+%   is detected when \cs{@@_to_other_loop:w} finds one of the trailing
+%   |A|, distinguished from any contents of the initial token list by
+%   their category.  Then \cs{@@_to_other_end:w} is called, and finds
+%   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
+  {
+    \exp_after:wN \@@_to_other_loop:w
+      \tl_to_str:n {#1} ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ A ~ \q_mark \q_stop
+  }
+\group_begin:
+\tex_lccode:D `\* = `\  %
+\tex_lccode:D `\A = `\A 
+\tex_lowercase:D
+  {
+    \group_end:
+    \cs_new:Npn \@@_to_other_loop:w
+      #1 ~ #2 ~ #3 ~ #4 ~ #5 ~ #6 ~ #7 ~ #8 ~ #9 \q_stop
+      {
+        \if_meaning:w A #8
+          \@@_to_other_end:w
+        \fi:
+        \@@_to_other_loop:w
+        #9 #1 * #2 * #3 * #4 * #5 * #6 * #7 * #8 * \q_stop
+      }
+    \cs_new:Npn \@@_to_other_end:w \fi: #1 \q_mark #2 * A #3 \q_stop
+      { \fi: #2 }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {\str_item:Nn, \str_item:cn, \str_item:nn, \str_item_ignore_spaces:nn}
+% \begin{macro}[EXP, aux]{\@@_item:nn, \@@_item:ww}
+%   The \cs{str_item:nn} hands its argument with spaces escaped to
+%   \cs{@@_item:nn}, and makes sure to turn the result back into
+%   a proper string (with category code~$10$ spaces) eventually.  The
+%   \cs{str_item_ignore_spaces:nn} function cheats a little bit in that
+%   it doesn't hand to \cs{@@_item:nn} an \enquote{other string}.
+%   This is safe, as everything else is done with undelimited arguments.
+%   Then evaluate the \meta{index} argument~|#2| and count characters in
+%   the string, passing those two numbers to \cs{@@_item:ww} for further
+%   analysis.  If the \meta{index} is negative, shift by |#2|, and
+%   remove that number of characters before returning the next item in
+%   the input stream (and if |#1| is smaller than $-|#2|$, nothing is
+%   returned).  If the \meta{index} is positive, ignore that number
+%   (minus one) of characters before returning the next one.  The shift
+%   by one is obtained by inserting an empty brace group before the
+%   string in that case: that brace group also covers the case where the
+%   \meta{index} is zero.
+%    \begin{macrocode}
+\cs_new_nopar:Npn \str_item:Nn { \exp_args:No \str_item:nn }
+\cs_generate_variant:Nn \str_item:Nn { c }
+\cs_new:Npn \str_item:nn #1#2
+  {
+    \exp_args:Nf \tl_to_str:n
+      {
+        \exp_args:Nf \@@_item:nn
+          { \@@_to_other:n {#1} } {#2}
+      }
+  }
+\cs_new:Npn \str_item_ignore_spaces:nn #1
+  { \exp_args:No \@@_item:nn { \tl_to_str:n {#1} } }
+\cs_new:Npn \@@_item:nn #1#2
+  {
+    \exp_after:wN \@@_item:ww
+    \int_use:N \__int_eval:w #2 \exp_after:wN ;
+    \__int_value:w \@@_count:n {#1} ;
+    #1 \q_stop
+  }
+\cs_new:Npn \@@_item:ww #1; #2;
+  {
+    \int_compare:nNnTF {#1} < \c_zero
+      {
+        \int_compare:nNnTF {#1} < {-#2}
+          { \use_none_delimit_by_q_stop:w }
+          {
+            \exp_after:wN \use_i_delimit_by_q_stop:nw
+            \exp:w \exp_after:wN \@@_skip_exp_end:w
+              \int_use:N \__int_eval:w #1 + #2 ;
+          }
+      }
+      {
+        \int_compare:nNnTF {#1} > {#2}
+          { \use_none_delimit_by_q_stop:w }
+          {
+            \exp_after:wN \use_i_delimit_by_q_stop:nw
+            \exp:w \@@_skip_exp_end:w #1 ; { }
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]{\@@_skip_exp_end:w}
+% \begin{macro}[EXP, aux]
+%   {\@@_skip_loop:wNNNNNNNN, \@@_skip_end:w, \@@_skip_end:NNNNNNNN}
+%   Removes |max(#1,0)| characters from the input stream, and then
+%   leaves \cs{exp_end:}.  This should be expanded using
+%   \cs{exp:w}.  We remove characters $8$ at a time until
+%   there are at most $8$ to remove.  Then we do a dirty trick: the
+%   \cs{if_case:w} construction leaves between $0$ and $8$ times the
+%   \cs{or:} control sequence, and those \cs{or:} become arguments of
+%   \cs{@@_skip_end:NNNNNNNN}.  If the number of characters to remove
+%   is $6$, say, then there are two \cs{or:} left, and the $8$ arguments
+%   of \cs{@@_skip_end:NNNNNNNN} are the two \cs{or:}, and $6$
+%   characters from the input stream, exactly what we wanted to
+%   remove. Then close the \cs{if_case:w} conditional with \cs{fi:}, and
+%   stop the initial expansion with \cs{exp_end:} (see places where
+%   \cs{@@_skip_exp_end:w} is called).
+%    \begin{macrocode}
+\cs_new:Npn \@@_skip_exp_end:w #1;
+  {
+    \if_int_compare:w #1 > \c_eight
+      \exp_after:wN \@@_skip_loop:wNNNNNNNN
+    \else:
+      \exp_after:wN \@@_skip_end:w
+      \int_use:N \__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_use:N \__int_eval:w #1 - \c_eight ; }
+\cs_new:Npn \@@_skip_end:w #1 ;
+  {
+    \exp_after:wN \@@_skip_end:NNNNNNNN
+    \if_case:w #1 \exp_stop_f: \or: \or: \or: \or: \or: \or: \or: \or:
+  }
+\cs_new:Npn \@@_skip_end:NNNNNNNN #1#2#3#4#5#6#7#8 { \fi: \exp_end: }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {\str_range:Nnn, \str_range:nnn, \str_range_ignore_spaces:nnn}
+% \begin{macro}[EXP, int]{\@@_range:nnn}
+% \begin{macro}[EXP, aux]{\@@_range:www, \@@_range:nnw}
+%   Sanitize the string.  Then evaluate the arguments.  At this stage we
+%   also decrement the \meta{start index}, since our goal is to know how
+%   many characters should be removed.  Then limit the range to be
+%   non-negative and at most the length of the string (this avoids
+%   needing to check for the end of the string when grabbing
+%   characters), shifting negative numbers by the appropriate amount.
+%   Afterwards, skip characters, then keep some more, and finally drop
+%   the end of the string.
+%    \begin{macrocode}
+\cs_new_nopar:Npn \str_range:Nnn { \exp_args:No \str_range:nnn }
+\cs_generate_variant:Nn \str_range:Nnn { c }
+\cs_new:Npn \str_range:nnn #1#2#3
+  {
+    \exp_args:Nf \tl_to_str:n
+      {
+        \exp_args:Nf \@@_range:nnn
+          { \@@_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} } }
+\cs_new:Npn \@@_range:nnn #1#2#3
+  {
+    \exp_after:wN \@@_range:www
+    \__int_value:w \@@_count:n {#1} \exp_after:wN ;
+    \int_use:N \__int_eval:w #2 - \c_one \exp_after:wN ;
+    \int_use:N \__int_eval:w #3 ;
+    #1 \q_stop
+  }
+\cs_new:Npn \@@_range:www #1; #2; #3;
+  {
+    \exp_args:Nf \@@_range:nnw
+      { \@@_range_normalize:nn {#2} {#1} }
+      { \@@_range_normalize:nn {#3} {#1} }
+  }
+\cs_new:Npn \@@_range:nnw #1#2
+  {
+    \exp_after:wN \@@_collect_delimit_by_q_stop:w
+    \int_use:N \__int_eval:w #2 - #1 \exp_after:wN ;
+    \exp:w \@@_skip_exp_end:w #1 ;
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}[EXP, aux]{\@@_range_normalize:nn}
+%   This function converts an \meta{index} argument into an explicit
+%   position in the string (a result of $0$ denoting \enquote{out of
+%     bounds}).  Expects two explicit integer arguments: the
+%   \meta{index} |#1| and the string count~|#2|.  If |#1| is negative,
+%   replace it by $|#1| + |#2| + 1$, then limit to the range $[0,
+%   |#2|]$.
+%    \begin{macrocode}
+\cs_new:Npn \@@_range_normalize:nn #1#2
+  {
+    \int_eval:n
+      {
+        \if_int_compare:w #1 < \c_zero
+          \if_int_compare:w #1 < -#2 \exp_stop_f:
+            \c_zero
+          \else:
+            #1 + #2 + \c_one
+          \fi:
+        \else:
+          \if_int_compare:w #1 < #2 \exp_stop_f:
+            #1
+          \else:
+            #2
+          \fi:
+        \fi:
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[EXP, aux]{\@@_collect_delimit_by_q_stop:w}
+% \begin{macro}[EXP, aux]
+%   {
+%     \@@_collect_loop:wn, \@@_collect_loop:wnNNNNNNN,
+%     \@@_collect_end:wn, \@@_collect_end:nnnnnnnnw
+%   }
+%   Collects |max(#1,0)| characters, and removes everything else until
+%   \cs{q_stop}. This is somewhat similar to \cs{@@_skip_exp_end:w}, but
+%   accepts integer expression arguments.  This time we can only grab
+%   $7$ characters at a time.  At the end, we use an \cs{if_case:w}
+%   trick again, so that the $8$ first arguments of
+%   \cs{@@_collect_end:nnnnnnnnw} are some \cs{or:}, followed by an
+%   \cs{fi:}, followed by |#1| characters from the input stream. Simply
+%   leaving this in the input stream will close the conditional properly
+%   and the \cs{or:} disappear.
+%    \begin{macrocode}
+\cs_new:Npn \@@_collect_delimit_by_q_stop:w #1;
+  { \@@_collect_loop:wn #1 ; { } }
+\cs_new:Npn \@@_collect_loop:wn #1 ;
+  {
+    \if_int_compare:w #1 > \c_seven
+      \exp_after:wN \@@_collect_loop:wnNNNNNNN
+    \else:
+      \exp_after:wN \@@_collect_end:wn
+    \fi:
+    #1 ;
+  }
+\cs_new:Npn \@@_collect_loop:wnNNNNNNN #1; #2 #3#4#5#6#7#8#9
+  {
+    \exp_after:wN \@@_collect_loop:wn
+    \int_use:N \__int_eval:w #1 - \c_seven ;
+    { #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 > \c_zero #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 }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Counting characters}
+%
+% \begin{macro}[EXP]
+%   {\str_count_spaces:N, \str_count_spaces:c, \str_count_spaces:n}
+% \begin{macro}[EXP, aux]{\@@_count_spaces_loop:wwwwwwwww}
+%   To speed up this function, we grab and discard $9$ space-delimited
+%   arguments in each iteration of the loop.  The loop stops when the
+%   last argument is one of the trailing |X|\meta{number}, and that
+%   \meta{number} is added to the sum of $9$ that precedes, to adjust
+%   the result.
+%    \begin{macrocode}
+\cs_new_nopar:Npn \str_count_spaces:N
+  { \exp_args:No \str_count_spaces:n }
+\cs_generate_variant:Nn \str_count_spaces:N { c }
+\cs_new:Npn \str_count_spaces:n #1
+  {
+    \int_eval:n
+      {
+        \exp_after:wN \@@_count_spaces_loop:wwwwwwwww
+        \tl_to_str:n {#1} ~
+        X 7 ~ X 6 ~ X 5 ~ X 4 ~ X 3 ~ X 2 ~ X 1 ~ X 0 ~ X -1 ~
+        \q_stop
+      }
+  }
+\cs_new:Npn \@@_count_spaces_loop:wwwwwwwww #1~#2~#3~#4~#5~#6~#7~#8~#9~
+  {
+    \if_meaning:w X #9
+      \use_i_delimit_by_q_stop:nw
+    \fi:
+    \c_nine + \@@_count_spaces_loop:wwwwwwwww
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {\str_count:N, \str_count:c, \str_count:n, \str_count_ignore_spaces:n}
+% \begin{macro}[EXP, int]{\@@_count:n}
+% \begin{macro}[EXP, aux]{\@@_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}.
+%   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
+%   \cs{tl_count:n}, which ignores spaces.  Since strings tend to be
+%   longer than token lists, we use specialized functions to count
+%   characters ignoring spaces.  Namely, loop, grabbing $9$ non-space
+%   characters at each step, and end as soon as we reach one of the $9$
+%   trailing items.  The \texttt{_unsafe} variant expects a token list
+%   already converted to category code $12$ characters, and is used by
+%   \cs{str_item:nn}.
+%    \begin{macrocode}
+\cs_new_nopar:Npn \str_count:N { \exp_args:No \str_count:n }
+\cs_generate_variant:Nn \str_count:N { c }
+\cs_new:Npn \str_count:n #1
+  {
+    \@@_count_aux:n
+      {
+        \str_count_spaces:n {#1}
+        + \exp_after:wN \@@_count_loop:NNNNNNNNN \tl_to_str:n {#1}
+      }
+  }
+\cs_new:Npn \@@_count:n #1
+  {
+    \@@_count_aux:n
+      { \@@_count_loop:NNNNNNNNN #1 }
+  }
+\cs_new:Npn \str_count_ignore_spaces:n #1
+  {
+    \@@_count_aux:n
+      { \exp_after:wN \@@_count_loop:NNNNNNNNN \tl_to_str:n {#1} }
+  }
+\cs_new:Npn \@@_count_aux:n #1
+  {
+    \int_eval:n
+      {
+        #1
+        { X \c_eight } { X \c_seven } { X \c_six   }
+        { X \c_five  } { X \c_four  } { X \c_three }
+        { X \c_two   } { X \c_one   } { X \c_zero  }
+        \q_stop
+      }
+  }
+\cs_new:Npn \@@_count_loop:NNNNNNNNN #1#2#3#4#5#6#7#8#9
+  {
+    \if_meaning:w X #9
+      \exp_after:wN \use_none_delimit_by_q_stop:w
+    \fi:
+    \c_nine + \@@_count_loop:NNNNNNNNN
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{The first character in a string}
+%
+% \begin{macro}[EXP]
+%   {\str_head:N, \str_head:c, \str_head:n, \str_head_ignore_spaces:n}
+% \begin{macro}[EXP, aux]{\@@_head:w}
+%   The \texttt{_ignore_spaces} variant is almost identical to
+%   \cs{tl_head:n}.  As usual, \cs{str_head:N} expands its argument and
+%   hands it to \cs{str_head:n}.  To circumvent the fact that \TeX{}
+%   skips spaces when grabbing undelimited macro parameters,
+%   \cs{@@_head:w} takes an argument delimited by a space. If |#1|
+%   starts with a non-space character, \cs{use_i_delimit_by_q_stop:nw}
+%   leaves that in the input stream. On the other hand, if |#1| starts
+%   with a space, the \cs{@@_head:w} takes an empty argument, and the
+%   single (initially braced) space in the definition of \cs{@@_head:w}
+%   makes its way to the output. Finally, for an empty argument, the
+%   (braced) empty brace group in the definition of \cs{str_head:n}
+%   gives an empty result after passing through
+%   \cs{use_i_delimit_by_q_stop:nw}.
+%    \begin{macrocode}
+\cs_new_nopar:Npn \str_head:N { \exp_args:No \str_head:n }
+\cs_generate_variant:Nn \str_head:N { c }
+\cs_set:Npn \str_head:n #1
+  {
+    \exp_after:wN \@@_head:w
+    \tl_to_str:n {#1}
+    { { } } ~ \q_stop
+  }
+\cs_set:Npn \@@_head:w #1 ~ %
+  { \use_i_delimit_by_q_stop:nw #1 { ~ } }
+\cs_new:Npn \str_head_ignore_spaces:n #1
+  {
+    \exp_after:wN \use_i_delimit_by_q_stop:nw
+    \tl_to_str:n {#1} { } \q_stop
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {\str_tail:N, \str_tail:c, \str_tail:n, \str_tail_ignore_spaces:n}
+% \begin{macro}[EXP, aux]{\@@_tail_auxi:w, \@@_tail_auxii:w}
+%   Getting the tail is a little bit more convoluted than the head of a
+%   string.  We hit the front of the string with \cs{reverse_if:N}
+%   \cs{if_charcode:w} \cs{scan_stop:}.  This removes the first
+%   character, and necessarily makes the test true, since the character
+%   cannot match \cs{scan_stop:}. The auxiliary function then inserts
+%   the required \cs{fi:} to close the conditional, and leaves the tail
+%   of the string in the input stream.  The details are such that an
+%   empty string has an empty tail (this requires in particular that the
+%   end-marker |X| be unexpandable and not a control sequence).  The
+%   \texttt{_ignore_spaces} is rather simpler: after converting the
+%   input to a string, \cs{@@_tail_auxii:w} removes one undelimited
+%   argument and leaves everything else until an end-marker \cs{q_mark}.
+%   One can check that an empty (or blank) string yields an empty
+%   tail.
+%    \begin{macrocode}
+\cs_new_nopar:Npn \str_tail:N { \exp_args:No \str_tail:n }
+\cs_generate_variant:Nn \str_tail:N { c }
+\cs_set:Npn \str_tail:n #1
+  {
+    \exp_after:wN \@@_tail_auxi:w
+    \reverse_if:N \if_charcode:w
+        \scan_stop: \tl_to_str:n {#1} X X \q_stop
+  }
+\cs_set:Npn \@@_tail_auxi:w #1 X #2 \q_stop { \fi: #1 }
+\cs_new:Npn \str_tail_ignore_spaces:n #1
+  {
+    \exp_after:wN \@@_tail_auxii:w
+    \tl_to_str:n {#1} \q_mark \q_mark \q_stop
+  }
+\cs_new:Npn \@@_tail_auxii:w #1 #2 \q_mark #3 \q_stop { #2 }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \subsection{String manipulation}
 %
 % \begin{macro}[EXP]
@@ -558,12 +1388,12 @@
 %     \str_lower_case:n, \str_lower_case:f,
 %     \str_upper_case:n, \str_upper_case:f
 %   }
-% \begin{macro}[aux, EXP]{\__str_change_case:nn}
-% \begin{macro}[aux, EXP]{\__str_change_case_aux:nn}
-% \begin{macro}[aux, EXP]{\__str_change_case_loop:nw}
-% \begin{macro}[aux, EXP]{\__str_change_case_space:n}
-% \begin{macro}[aux, EXP]{\__str_change_case_char:nN}
-% \begin{macro}[aux, EXP]{\__str_change_case_char:NNNNNNNNn}
+% \begin{macro}[aux, EXP]{\@@_change_case:nn}
+% \begin{macro}[aux, EXP]{\@@_change_case_aux:nn}
+% \begin{macro}[aux, EXP]{\@@_change_case_loop:nw}
+% \begin{macro}[aux, EXP]{\@@_change_case_space:n}
+% \begin{macro}[aux, EXP]{\@@_change_case_char:nN}
+% \begin{macro}[aux, EXP]{\@@_change_case_char:NNNNNNNNn}
 %   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
@@ -571,45 +1401,45 @@
 %   data files based on the character code of the current character is
 %   shared with the text case changer too.
 %    \begin{macrocode}
-\cs_new:Npn \str_fold_case:n #1 { \__str_change_case:nn {#1} { fold } }
-\cs_new:Npn \str_lower_case:n #1 { \__str_change_case:nn {#1} { lower } }
-\cs_new:Npn \str_upper_case:n #1 { \__str_change_case:nn {#1} { upper } }
+\cs_new:Npn \str_fold_case:n #1 { \@@_change_case:nn {#1} { fold } }
+\cs_new:Npn \str_lower_case:n #1 { \@@_change_case:nn {#1} { lower } }
+\cs_new:Npn \str_upper_case:n #1 { \@@_change_case:nn {#1} { upper } }
 \cs_generate_variant:Nn \str_fold_case:n  { V }
 \cs_generate_variant:Nn \str_lower_case:n { f }
 \cs_generate_variant:Nn \str_upper_case:n { f }
-\cs_new:Npn \__str_change_case:nn #1
+\cs_new:Npn \@@_change_case:nn #1
   {
-    \exp_after:wN \__str_change_case_aux:nn \exp_after:wN
+    \exp_after:wN \@@_change_case_aux:nn \exp_after:wN
       { \tl_to_str:n {#1} }
   }
-\cs_new:Npn \__str_change_case_aux:nn #1#2
+\cs_new:Npn \@@_change_case_aux:nn #1#2
   {
-    \__str_change_case_loop:nw {#2} #1 \q_recursion_tail \q_recursion_stop
+    \@@_change_case_loop:nw {#2} #1 \q_recursion_tail \q_recursion_stop
   }
-\cs_new:Npn \__str_change_case_loop:nw #1#2 \q_recursion_stop
+\cs_new:Npn \@@_change_case_loop:nw #1#2 \q_recursion_stop
   {
     \tl_if_head_is_space:nTF {#2}
-      { \__str_change_case_space:n }
-      { \__str_change_case_char:nN }
+      { \@@_change_case_space:n }
+      { \@@_change_case_char:nN }
     {#1} #2 \q_recursion_stop
   }
 \use:x
-  { \cs_new:Npn \exp_not:N \__str_change_case_space:n ##1 \c_space_tl }
+  { \cs_new:Npn \exp_not:N \@@_change_case_space:n ##1 \c_space_tl }
   {
     \c_space_tl
-    \__str_change_case_loop:nw {#1}
+    \@@_change_case_loop:nw {#1}
   }
-\cs_new:Npn \__str_change_case_char:nN #1#2
+\cs_new:Npn \@@_change_case_char:nN #1#2
   {
     \quark_if_recursion_tail_stop:N #2
     \exp_args:Nf \tl_to_str:n
       {
-        \exp_after:wN \__str_change_case_char:NNNNNNNNn
+        \exp_after:wN \@@_change_case_char:NNNNNNNNn
           \int_use:N \__int_eval:w 1000000 + `#2 \__int_eval_end: #2 {#1}
       }
-    \__str_change_case_loop:nw {#1}
+    \@@_change_case_loop:nw {#1}
   }
-\cs_new:Npn \__str_change_case_char:NNNNNNNNn #1#2#3#4#5#6#7#8#9
+\cs_new:Npn \@@_change_case_char:NNNNNNNNn #1#2#3#4#5#6#7#8#9
   {
     \str_case:nvF #8
       { c__unicode_ #9 _ #6 _X_ #7 _tl }
@@ -624,10 +1454,60 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{variable}
+%   {
+%     \c_ampersand_str,
+%     \c_backslash_str,
+%     \c_left_brace_str,
+%     \c_right_brace_str,
+%     \c_circumflex_str,
+%     \c_colojn_str,
+%     \c_hash_str,
+%     \c_percent_str,
+%     \c_tilde_str,
+%     \c_underscore_str
+%   }
+%   For all of those strings, use \cs{cs_to_str:N} to get characters with
+%   the correct category code without worries
+%    \begin{macrocode}
+\str_const:Nx \c_ampersand_str   { \cs_to_str:N \& }
+\str_const:Nx \c_backslash_str   { \cs_to_str:N \\ }
+\str_const:Nx \c_left_brace_str  { \cs_to_str:N \{ }
+\str_const:Nx \c_right_brace_str { \cs_to_str:N \} }
+\str_const:Nx \c_circumflex_str  { \cs_to_str:N \^ }
+\str_const:Nx \c_colon_str       { \cs_to_str:N \: }
+\str_const:Nx \c_hash_str        { \cs_to_str:N \# }
+\str_const:Nx \c_percent_str     { \cs_to_str:N \% }
+\str_const:Nx \c_tilde_str       { \cs_to_str:N \~ }
+\str_const:Nx \c_underscore_str  { \cs_to_str:N \_ }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_tmpa_str, \l_tmpb_str, \g_tmpa_str, \g_tmpb_str}
+%   Scratch strings.
+%    \begin{macrocode}
+\str_new:N \l_tmpa_str
+\str_new:N \l_tmpb_str
+\str_new:N \g_tmpa_str
+\str_new:N \g_tmpb_str
+%    \end{macrocode}
+% \end{variable}
+%
+% \subsection{Viewing strings}
+%
+% \begin{macro}{\str_show:n, \str_show:N, \str_show:c}
+%   Displays a string on the terminal.
+%    \begin{macrocode}
+\cs_new_eq:NN \str_show:n \tl_show:n
+\cs_new_eq:NN \str_show:N \tl_show:N
+\cs_generate_variant:Nn \str_show:N { c }
+%    \end{macrocode}
+% \end{macro}
+%
 %    \begin{macrocode}
 %</initex|package>
 %    \end{macrocode}
 %
 % \end{implementation}
 %
-% \PrintIndex
+% \PrintIndex
\ No newline at end of file
diff --git a/l3kernel/testfiles/m3expl001.luatex.tlg b/l3kernel/testfiles/m3expl001.luatex.tlg
index 45b78e8..ef869ca 100644
--- a/l3kernel/testfiles/m3expl001.luatex.tlg
+++ b/l3kernel/testfiles/m3expl001.luatex.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_escape_x:n on line ...
 Defining \__str_if_eq_x_return:nn on line ...
@@ -626,6 +686,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -652,6 +728,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -664,6 +784,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2401,9 +2538,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl001.ptex.tlg b/l3kernel/testfiles/m3expl001.ptex.tlg
index 9b0b1d1..fd6b07f 100644
--- a/l3kernel/testfiles/m3expl001.ptex.tlg
+++ b/l3kernel/testfiles/m3expl001.ptex.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_if_eq_x_return:nn on line ...
 Defining \str_if_eq_p:nn on line ...
@@ -625,6 +685,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -651,6 +727,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -663,6 +783,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2400,9 +2537,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl001.tlg b/l3kernel/testfiles/m3expl001.tlg
index 274ce20..fe1d9d2 100644
--- a/l3kernel/testfiles/m3expl001.tlg
+++ b/l3kernel/testfiles/m3expl001.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_if_eq_x_return:nn on line ...
 Defining \str_if_eq_p:nn on line ...
@@ -625,6 +685,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -651,6 +727,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -663,6 +783,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2400,9 +2537,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl001.uptex.tlg b/l3kernel/testfiles/m3expl001.uptex.tlg
index 9b0b1d1..fd6b07f 100644
--- a/l3kernel/testfiles/m3expl001.uptex.tlg
+++ b/l3kernel/testfiles/m3expl001.uptex.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_if_eq_x_return:nn on line ...
 Defining \str_if_eq_p:nn on line ...
@@ -625,6 +685,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -651,6 +727,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -663,6 +783,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2400,9 +2537,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl001.xetex.tlg b/l3kernel/testfiles/m3expl001.xetex.tlg
index b08c015..34b64d5 100644
--- a/l3kernel/testfiles/m3expl001.xetex.tlg
+++ b/l3kernel/testfiles/m3expl001.xetex.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_if_eq_x_return:nn on line ...
 Defining \str_if_eq_p:nn on line ...
@@ -625,6 +685,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -651,6 +727,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -663,6 +783,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2400,9 +2537,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl003.luatex.tlg b/l3kernel/testfiles/m3expl003.luatex.tlg
index b15d077..af27508 100644
--- a/l3kernel/testfiles/m3expl003.luatex.tlg
+++ b/l3kernel/testfiles/m3expl003.luatex.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_escape_x:n on line ...
 Defining \__str_if_eq_x_return:nn on line ...
@@ -626,6 +686,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -652,6 +728,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -664,6 +784,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2402,9 +2539,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl003.ptex.tlg b/l3kernel/testfiles/m3expl003.ptex.tlg
index 44aa817..6b56bb5 100644
--- a/l3kernel/testfiles/m3expl003.ptex.tlg
+++ b/l3kernel/testfiles/m3expl003.ptex.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_if_eq_x_return:nn on line ...
 Defining \str_if_eq_p:nn on line ...
@@ -625,6 +685,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -651,6 +727,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -663,6 +783,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2401,9 +2538,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl003.tlg b/l3kernel/testfiles/m3expl003.tlg
index 03aba44..86c3f18 100644
--- a/l3kernel/testfiles/m3expl003.tlg
+++ b/l3kernel/testfiles/m3expl003.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_if_eq_x_return:nn on line ...
 Defining \str_if_eq_p:nn on line ...
@@ -625,6 +685,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -651,6 +727,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -663,6 +783,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2401,9 +2538,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl003.uptex.tlg b/l3kernel/testfiles/m3expl003.uptex.tlg
index 44aa817..6b56bb5 100644
--- a/l3kernel/testfiles/m3expl003.uptex.tlg
+++ b/l3kernel/testfiles/m3expl003.uptex.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_if_eq_x_return:nn on line ...
 Defining \str_if_eq_p:nn on line ...
@@ -625,6 +685,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -651,6 +727,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -663,6 +783,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2401,9 +2538,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3kernel/testfiles/m3expl003.xetex.tlg b/l3kernel/testfiles/m3expl003.xetex.tlg
index bc3b4aa..670e8f5 100644
--- a/l3kernel/testfiles/m3expl003.xetex.tlg
+++ b/l3kernel/testfiles/m3expl003.xetex.tlg
@@ -591,10 +591,70 @@ Defining \g_tmpa_tl on line ...
 Defining \g_tmpb_tl on line ...
 Defining \l_tmpa_tl on line ...
 Defining \l_tmpb_tl on line ...
-Defining \str_head:n on line ...
-Defining \__str_head:w on line ...
-Defining \str_tail:n on line ...
-Defining \__str_tail:w on line ...
+Defining \str_new:N on line ...
+Defining \str_new:c on line ...
+Defining \str_use:N on line ...
+Defining \str_use:c on line ...
+Defining \str_clear:N on line ...
+Defining \str_clear:c on line ...
+Defining \str_gclear:N on line ...
+Defining \str_gclear:c on line ...
+Defining \str_clear_new:N on line ...
+Defining \str_clear_new:c on line ...
+Defining \str_gclear_new:N on line ...
+Defining \str_gclear_new:c on line ...
+Defining \str_set_eq:NN on line ...
+Defining \str_gset_eq:NN on line ...
+Defining \str_set_eq:cN on line ...
+Defining \str_set_eq:Nc on line ...
+Defining \str_set_eq:cc on line ...
+Defining \str_gset_eq:cN on line ...
+Defining \str_gset_eq:Nc on line ...
+Defining \str_gset_eq:cc on line ...
+Defining \str_set:Nn on line ...
+Defining \str_set:Nx on line ...
+Defining \str_set:cn on line ...
+Defining \str_set:cx on line ...
+Defining \str_gset:Nn on line ...
+Defining \str_gset:Nx on line ...
+Defining \str_gset:cn on line ...
+Defining \str_gset:cx on line ...
+Defining \str_const:Nn on line ...
+Defining \str_const:Nx on line ...
+Defining \str_const:cn on line ...
+Defining \str_const:cx on line ...
+Defining \str_put_left:Nn on line ...
+Defining \str_put_left:Nx on line ...
+Defining \str_put_left:cn on line ...
+Defining \str_put_left:cx on line ...
+Defining \str_gput_left:Nn on line ...
+Defining \str_gput_left:Nx on line ...
+Defining \str_gput_left:cn on line ...
+Defining \str_gput_left:cx on line ...
+Defining \str_put_right:Nn on line ...
+Defining \str_put_right:Nx on line ...
+Defining \str_put_right:cn on line ...
+Defining \str_put_right:cx on line ...
+Defining \str_gput_right:Nn on line ...
+Defining \str_gput_right:Nx on line ...
+Defining \str_gput_right:cn on line ...
+Defining \str_gput_right:cx on line ...
+Defining \str_if_exist_p:N on line ...
+Defining \str_if_exist:NT on line ...
+Defining \str_if_exist:NF on line ...
+Defining \str_if_exist:NTF on line ...
+Defining \str_if_exist_p:c on line ...
+Defining \str_if_exist:cT on line ...
+Defining \str_if_exist:cF on line ...
+Defining \str_if_exist:cTF on line ...
+Defining \str_if_empty_p:N on line ...
+Defining \str_if_empty:NT on line ...
+Defining \str_if_empty:NF on line ...
+Defining \str_if_empty:NTF on line ...
+Defining \str_if_empty_p:c on line ...
+Defining \str_if_empty:cT on line ...
+Defining \str_if_empty:cF on line ...
+Defining \str_if_empty:cTF on line ...
 Defining \__str_if_eq_x:nn on line ...
 Defining \__str_if_eq_x_return:nn on line ...
 Defining \str_if_eq_p:nn on line ...
@@ -625,6 +685,22 @@ Defining \str_if_eq_x_p:nn on line ...
 Defining \str_if_eq_x:nnT on line ...
 Defining \str_if_eq_x:nnF on line ...
 Defining \str_if_eq_x:nnTF on line ...
+Defining \str_if_eq_p:NN on line ...
+Defining \str_if_eq:NNTF on line ...
+Defining \str_if_eq:NNT on line ...
+Defining \str_if_eq:NNF on line ...
+Defining \str_if_eq:cNT on line ...
+Defining \str_if_eq:NcT on line ...
+Defining \str_if_eq:ccT on line ...
+Defining \str_if_eq:cNF on line ...
+Defining \str_if_eq:NcF on line ...
+Defining \str_if_eq:ccF on line ...
+Defining \str_if_eq:cNTF on line ...
+Defining \str_if_eq:NcTF on line ...
+Defining \str_if_eq:ccTF on line ...
+Defining \str_if_eq_p:cN on line ...
+Defining \str_if_eq_p:Nc on line ...
+Defining \str_if_eq_p:cc on line ...
 Defining \str_case:nn on line ...
 Defining \str_case:nnT on line ...
 Defining \str_case:nnF on line ...
@@ -651,6 +727,50 @@ Defining \str_case_x:nnTF on line ...
 Defining \__str_case_x:nnTF on line ...
 Defining \__str_case_x:nw on line ...
 Defining \__str_case_end:nw on line ...
+Defining \__str_to_other:n on line ...
+Defining \__str_to_other_loop:w on line ...
+Defining \__str_to_other_end:w on line ...
+Defining \str_item:Nn on line ...
+Defining \str_item:cn on line ...
+Defining \str_item:nn on line ...
+Defining \str_item_ignore_spaces:nn on line ...
+Defining \__str_item:nn on line ...
+Defining \__str_item:ww on line ...
+Defining \__str_skip_exp_end:w on line ...
+Defining \__str_skip_loop:wNNNNNNNN on line ...
+Defining \__str_skip_end:w on line ...
+Defining \__str_skip_end:NNNNNNNN on line ...
+Defining \str_range:Nnn on line ...
+Defining \str_range:cnn on line ...
+Defining \str_range:nnn on line ...
+Defining \str_range_ignore_spaces:nnn on line ...
+Defining \__str_range:nnn on line ...
+Defining \__str_range:www on line ...
+Defining \__str_range:nnw on line ...
+Defining \__str_range_normalize:nn on line ...
+Defining \__str_collect_delimit_by_q_stop:w on line ...
+Defining \__str_collect_loop:wn on line ...
+Defining \__str_collect_loop:wnNNNNNNN on line ...
+Defining \__str_collect_end:wn on line ...
+Defining \__str_collect_end:nnnnnnnnw on line ...
+Defining \str_count_spaces:N on line ...
+Defining \str_count_spaces:c on line ...
+Defining \str_count_spaces:n on line ...
+Defining \__str_count_spaces_loop:wwwwwwwww on line ...
+Defining \str_count:N on line ...
+Defining \str_count:c on line ...
+Defining \str_count:n on line ...
+Defining \__str_count:n on line ...
+Defining \str_count_ignore_spaces:n on line ...
+Defining \__str_count_aux:n on line ...
+Defining \__str_count_loop:NNNNNNNNN on line ...
+Defining \str_head:N on line ...
+Defining \str_head:c on line ...
+Defining \str_head_ignore_spaces:n on line ...
+Defining \str_tail:N on line ...
+Defining \str_tail:c on line ...
+Defining \str_tail_ignore_spaces:n on line ...
+Defining \__str_tail_auxii:w on line ...
 Defining \str_fold_case:n on line ...
 Defining \str_lower_case:n on line ...
 Defining \str_upper_case:n on line ...
@@ -663,6 +783,23 @@ Defining \__str_change_case_loop:nw on line ...
 Defining \__str_change_case_space:n on line ...
 Defining \__str_change_case_char:nN on line ...
 Defining \__str_change_case_char:NNNNNNNNn on line ...
+Defining \c_ampersand_str on line ...
+Defining \c_backslash_str on line ...
+Defining \c_left_brace_str on line ...
+Defining \c_right_brace_str on line ...
+Defining \c_circumflex_str on line ...
+Defining \c_colon_str on line ...
+Defining \c_hash_str on line ...
+Defining \c_percent_str on line ...
+Defining \c_tilde_str on line ...
+Defining \c_underscore_str on line ...
+Defining \l_tmpa_str on line ...
+Defining \l_tmpb_str on line ...
+Defining \g_tmpa_str on line ...
+Defining \g_tmpb_str on line ...
+Defining \str_show:n on line ...
+Defining \str_show:N on line ...
+Defining \str_show:c on line ...
 Defining \__seq_item:n on line ...
 Defining \l__seq_internal_a_tl on line ...
 Defining \l__seq_internal_b_tl on line ...
@@ -2401,9 +2538,6 @@ Defining \__iow_wrap_newline: on line ...
 Defining \__iow_wrap_indent: on line ...
 Defining \__iow_wrap_unindent: on line ...
 Defining \__iow_wrap_end: on line ...
-Defining \__str_count_ignore_spaces:N on line ...
-Defining \__str_count_ignore_spaces:n on line ...
-Defining \__str_count_loop:NNNNNNNNN on line ...
 Defining message LaTeX/kernel/file-not-found on line ...
 Defining message LaTeX/kernel/input-streams-exhausted on line ...
 Defining message LaTeX/kernel/output-streams-exhausted on line ...
diff --git a/l3experimental/l3str/testfiles/m3str002.lvt b/l3kernel/testfiles/m3str003.lvt
similarity index 100%
rename from l3experimental/l3str/testfiles/m3str002.lvt
rename to l3kernel/testfiles/m3str003.lvt
diff --git a/l3experimental/l3str/testfiles/m3str002.tlg b/l3kernel/testfiles/m3str003.tlg
similarity index 100%
rename from l3experimental/l3str/testfiles/m3str002.tlg
rename to l3kernel/testfiles/m3str003.tlg

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the latex3-commits mailing list