% \iffalse meta-comment
%
%% File: l3msg.dtx Copyright (C) 2009-2011 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 "expl3 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>
\RequirePackage{l3names}
\GetIdInfo$Id: l3msg.dtx 2551 2011-08-11 22:40:53Z bruno $
  {L3 Experimental messages}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{l3msg} package\\ Messages^^A
%   \thanks{This file describes v\ExplFileVersion,
%      last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
%  The \LaTeX3 Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released \ExplFileDate}
%
% \maketitle
%
% \begin{documentation}
%
% Messages need to be passed to the user by modules, either when errors
% occur or to indicate how the code is proceeding. The \pkg{l3msg}
% module provides a consistent method for doing this (as opposed to
% writing directly to the terminal or log).
%
% The system used by \pkg{l3msg} to create messages divides the process
% into two distinct parts. Named messages are created in the first part
% of the process; at this stage, no decision is made about the type
% output that the message will produce. The second part of the process
% is actually producing a message. At this stage a choice of message
% \emph{class} has to be made, for example \texttt{error},
% \texttt{warning} or \texttt{info}.
%
% By separating out the creation and use of messages, several benefits
% are available. First, the messages can be altered later without
% needing details of where they are used in the code. This makes it
% possible to alter the language used, the detail level and so on.
% Secondly, the output which results from a given message can be
% altered. This can be done on a message class, module or message name
% basis. In this way, message behaviour can be altered and messages can
% be entirely suppressed.
%
% \section{Creating new messages}
%
% All messages have to be created before they can be used. All message
% setting is local, with the general assumption that messages will
% be managed as part of module set up outside of any \TeX{} grouping.
%
% The text of messages will automatically by wrapped to the length
% available in the console. As a result, formatting is only needed
% where it will help to show meaning. In particular, |\\| may be
% used to force a new line and \verb*|\ | forces an explicit space.
%
% \begin{function}{\msg_new:nnnn, \msg_new:nnn}
%   \begin{syntax}
%     \cs{msg_new:nnnn} \Arg{module} \Arg{message} \Arg{text}
%     ~~\Arg{more text}
%   \end{syntax}
%   Creates a \meta{message} for a given \meta{module}.
%   The message will be defined to first give \meta{text} and then
%   \meta{more text} if the user requests it. If no \meta{more text} is
%   available then a standard text is given instead. Within \meta{text}
%   and \meta{more text} four parameters (|#1| to |#4|) can be used:
%   these will be supplied at the time the message is used. The
%   parameters will be expanded when the message is used. Within the
%   \meta{text} and \meta{more text} |\\| can be used to start a new
%   line. An error will be raised if the \meta{message} already exists.
% \end{function}
%
% \begin{function}{\msg_set:nnnn, \msg_set:nnn}
%   \begin{syntax}
%     \cs{msg_set:nnnn} \Arg{module} \Arg{message} \Arg{text}
%     ~~\Arg{more text}
%   \end{syntax}
%   Sets up the text for a \meta{message} for a given \meta{module}.
%   The message will be defined to first give \meta{text} and then
%   \meta{more text} if the user requests it. If no \meta{more text} is
%   available then a standard text is given instead. Within \meta{text}
%   and \meta{more text} four parameters (|#1| to |#4|) can be used:
%   these will be supplied at the time the message is used. The
%   parameters will be expanded when the message is used. Within the
%   \meta{text} and \meta{more text} |\\| can be used to start a new
%   line.
% \end{function}
%
% \section{Contextual information for messages}
%
% \begin{function}[EXP]{\msg_line_context:}
%   \begin{syntax}
%     \cs{msg_line_context:}
%   \end{syntax}
%   Prints the current line number when a message is given, and
%   thus suitable for giving context to messages. The number itself
%   is proceeded by the text |on line|.
% \end{function}
%
% \begin{function}[EXP]{\msg_line_number:}
%   \begin{syntax}
%     \cs{msg_line_number:}
%   \end{syntax}
%   Prints the current line number when a message is given.
% \end{function}
%
% \begin{variable}{\c_msg_return_text_tl}
%  Standard text to indicate that the user should try pressing
%  \meta{return} to continue. The standard definition reads:
%  \begin{verbatim}
%    Try typing <return> to proceed.
%
%    If that doesn't work, type X <return> to quit.
%  \end{verbatim}
% \end{variable}
%
% \begin{variable}{\c_msg_trouble_text_tl}
%  Standard text to indicate that the more errors are likely and
%  that aborting the run is advised. The standard definition reads:
%  \begin{verbatim}
%    More errors will almost certainly follow:
%    the LaTeX run should be aborted.
%  \end{verbatim}
% \end{variable}
%
% \begin{function}[EXP]{\msg_fatal_text:n}
%   \begin{syntax}
%     \cs{msg_fatal_text:n} \Arg{module}
%   \end{syntax}
%   Produces the standard text:
%   \begin{verbatim}
%     Fatal <module> error
%   \end{verbatim}
%   This function can be redefined to alter the language in which the
%   message is give, using |#1| as the name of the \meta{module} to
%   be included.
% \end{function}
%
% \begin{function}[EXP]{\msg_critical_text:n}
%   \begin{syntax}
%     \cs{msg_critical_text:n} \Arg{module}
%   \end{syntax}
%   Produces the standard text:
%   \begin{verbatim}
%     Critical <module> error
%   \end{verbatim}
%   This function can be redefined to alter the language in which the
%   message is give, using |#1| as the name of the \meta{module} to
%   be included.
% \end{function}
%
% \begin{function}[EXP]{\msg_error_text:n}
%   \begin{syntax}
%     \cs{msg_error_text:n} \Arg{module}
%   \end{syntax}
%   Produces the standard text:
%   \begin{verbatim}
%     <module> error
%   \end{verbatim}
%   This function can be redefined to alter the language in which the
%   message is give, using |#1| as the name of the \meta{module} to
%   be included.
% \end{function}
%
% \begin{function}[EXP]{\msg_warning_text:n}
%   \begin{syntax}
%     \cs{msg_warning_text:n} \Arg{module}
%   \end{syntax}
%   Produces the standard text:
%   \begin{verbatim}
%     <module> warning
%   \end{verbatim}
%   This function can be redefined to alter the language in which the
%   message is give, using |#1| as the name of the \meta{module} to
%   be included.
% \end{function}
%
% \begin{function}[EXP]{\msg_info_text:n}
%   \begin{syntax}
%     \cs{msg_info_text:n} \Arg{module}
%   \end{syntax}
%   Produces the standard text:
%   \begin{verbatim}
%     <module> info
%   \end{verbatim}
%   This function can be redefined to alter the language in which the
%   message is give, using |#1| as the name of the \meta{module} to
%   be included.
% \end{function}
%
% \section{Issuing messages}
%
% Messages behave differently depending on the message class. A number
% of standard message classes are supplied, but more can be
% created.
% 
% When issuing messages, any arguments passed should use
% \cs{tl_to_str:n} or \cs{token_to_str:N} to prevent unwanted expansion
% of the material.
%
% \begin{function}{\msg_class_set:nn}
%   \begin{syntax}
%     \cs{msg_class_set:nn} \Arg{class} \Arg{code}
%   \end{syntax}
%   Sets a \meta{class} to output a message, using \meta{code}
%   to process the message text. The \meta{class} should be a text
%   value, while the \meta{code} may be any arbitrary material.
%   The \meta{code} will receive $6$ arguments: the module
%   name (|#1|), the message name (|#2|) and the four arguments
%   taken by the message text (|#3| to |#6|).
% \end{function}
%
% The kernel defines several common message classes. The following
% describes the standard behaviour of each class if no redirection of
% the class or message is active. In all cases, the message may be
% issued supplying $0$ to $4$ arguments. The code will
% ensure that there an no errors if the number of arguments supplied
% here does not match the number in the definition of the message
% (although of course the sense of the message may be impaired).
%
% \begin{function}
%   {
%     \msg_fatal:nnxxxx ,
%     \msg_fatal:nnxxx  ,
%     \msg_fatal:nnxx   ,
%     \msg_fatal:nnx    ,
%     \msg_fatal:nn
%   }
%   \begin{syntax}
%     \cs{msg_fatal:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%       ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Issues \meta{module} error \meta{message}, passing \meta{arg one} to
%   \meta{arg four} to the text-creating functions. After issuing a
%   fatal error the \TeX{} run will halt.
% \end{function}
%
% \begin{function}
%   {
%    \msg_critical:nnxxxx ,
%    \msg_critical:nnxxx  ,
%    \msg_critical:nnxx   ,
%    \msg_critical:nnx    ,
%    \msg_critical:nn
%  }
%   \begin{syntax}
%     \cs{msg_critical:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%      ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Issues \meta{module} error \meta{message}, passing \meta{arg one} to
%   \meta{arg four} to the text-creating functions. After issuing the
%   message reading the current input file will stop. This may halt
%   the \TeX{} run (if the current file is the main file) or
%   may abort reading a sub-file.
% \end{function}
%
% \begin{function}
%   {
%     \msg_error:nnxxxx ,
%     \msg_error:nnxxx  ,
%     \msg_error:nnxx   ,
%     \msg_error:nnx    ,
%     \msg_error:nn
%   }
%   \begin{syntax}
%     \cs{msg_error:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%      ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Issues \meta{module} error \meta{message}, passing \meta{arg one} to
%   \meta{arg four} to the text-creating functions. The error will
%   stop processing and issue the text at the terminal. After user input,
%   the run will continue.
% \end{function}
%
%  \begin{function}
%    {
%      \msg_warning:nnxxxx ,
%      \msg_warning:nnxxx  ,
%      \msg_warning:nnxx   ,
%      \msg_warning:nnx    ,
%      \msg_warning:nn
%    }
%    \begin{syntax}
%      \cs{msg_warning:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%       ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%    \end{syntax}
%    Issues \meta{module} warning \meta{message}, passing \meta{arg one} to
%    \meta{arg four} to the text-creating functions. The warning text
%    will be added to the log file, but the \TeX{} run will not be
%    interrupted.
%  \end{function}
%
% \begin{function}
%   {
%     \msg_info:nnxxxx ,
%     \msg_info:nnxxx  ,
%     \msg_info:nnxx   ,
%     \msg_info:nnx    ,
%     \msg_info:nn
%   }
%   \begin{syntax}
%     \cs{msg_info:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%      ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Issues \meta{module} information \meta{message}, passing
%   \meta{arg one} to \meta{arg four} to the text-creating functions.
%   The information text will be added to the log file.
% \end{function}
%
% \begin{function}
%   {
%     \msg_log:nnxxxx ,
%     \msg_log:nnxxx  ,
%     \msg_log:nnxx   ,
%     \msg_log:nnx    ,
%     \msg_log:nn
%   }
%   \begin{syntax}
%     \cs{msg_log:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%      ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Issues \meta{module} information \meta{message}, passing
%   \meta{arg one} to \meta{arg four} to the text-creating functions.
%   The information text will be added to the log file: the output
%   is briefer than \cs{msg_info:nnxxxx}.
% \end{function}
%
% \begin{function}
%   {
%     \msg_none:nnxxxx ,
%     \msg_none:nnxxx  ,
%     \msg_none:nnxx   ,
%     \msg_none:nnx    ,
%     \msg_none:nn
%   }
%   \begin{syntax}
%     \cs{msg_none:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%      ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Does nothing: used as a message class to prevent any output at
%   all (see the discussion of message redirection).
% \end{function}
%
% \section{Redirecting messages}
%
% \begin{function}{\msg_redirect_class:nn}
%   \begin{syntax}
%     \cs{msg_redirect_class:nn} \Arg{class one} \Arg{class two}
%   \end{syntax}
%   Changes the behaviour of messages of \meta{class one} so that they
%   are processed using the code for those of \meta{class two}. Multiple
%   redirections are possible. Redirection to a missing class or
%   infinite loops will raise errors when the messages are used,
%   rather than at the point of redirection.
% \end{function}
%
% \begin{function}{\msg_redirect_module:nnn}
%   \begin{syntax}
%     \cs{msg_redirect_module:nnn} \Arg{module} \Arg{class one}
%     ~~\Arg{class two}
%   \end{syntax}
%   Redirects message of \meta{class one} for \meta{module} to act as
%   though they were from \meta{class two}. Messages of \meta{class one}
%   from sources other than \meta{module} are not affected by this
%   redirection. This function can be used to make some messages
%   \enquote{silent} by default. For example, all of the
%   \texttt{trace} messages of \meta{module} could be turned off with:
%   \begin{verbatim}
%     \msg_redirect_module:nnn { module } { trace } { none }
%   \end{verbatim}
% \end{function}
%
% \begin{function}{\msg_redirect_name:nnn}
%   \begin{syntax}
%     \cs{msg_redirect_name:nn} \Arg{module} \Arg{message} \Arg{class}
%   \end{syntax}
%   Redirects a specific \meta{message} from a specific \meta{module}
%   to act as a member of \meta{class} of messages. This function can
%   be used to make a selected message \enquote{silent} without
%   changing global parameters:
%   \begin{verbatim}
%     \msg_redirect_name:nnn { module } { annoying-message } { none }
%   \end{verbatim}
% \end{function}
%
% \section{Low-level message functions}
%
% The lower-level message functions should usually be accessed from the
% higher-level system. However, there are occasions where direct
% access to these functions is desirable.
%
% \begin{function}[EXP]{\msg_newline:, \msg_two_newlines:}
%   \begin{syntax}
%     \cs{msg_newline:}
%   \end{syntax}
%   Forces a new line in a message. This is a low-level function, which
%   will not include any additional printing information in the message:
%   contrast with |\\| in messages. The |two| version adds two lines.
% \end{function}
% 
% \begin{function}{\msg_interrupt:xxx}
%   \begin{syntax}
%     \cs{msg_interrupt:xxx} \Arg{first line} \Arg{text} \Arg{extra text}
%   \end{syntax}
%   Interrupts the \TeX{} run, issuing a formatted message comprising
%   \meta{first line} and \meta{text} laid out in the format
%   \begin{verbatim}
%     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
%     !
%     ! <first line>
%     ! 
%     ! <text>
%     !............................................... 
%   \end{verbatim}
%   where the \meta{text} will be wrapped to fit within the current
%   line length. The user may then request more information, at which 
%   stage the \meta{extra text} will be shown in the terminal in the
%   format
%   \begin{verbatim}
%     |'''''''''''''''''''''''''''''''''''''''''''''''
%     |  <extra text>
%     |...............................................
%   \end{verbatim}
%   where the \meta{extra text} will be wrapped to fit within the current
%   line length.
% \end{function}
%
% \begin{function}{\msg_log:x}
%   \begin{syntax}
%     \cs{msg_log:x} \Arg{text}
%   \end{syntax}
%   Writes to the log file with the \meta{text} laid out in the format
%   \begin{verbatim}
%     .................................................
%     . <text>
%     .................................................
%   \end{verbatim}
%   where the \meta{text} will be wrapped to fit within the current
%   line length. 
% \end{function}
%
% \begin{function}{\msg_term:x}
%   \begin{syntax}
%     \cs{msg_term:x} \Arg{text}
%   \end{syntax}
%   Writes to the terminal and log file with the \meta{text} laid out in the
%   format
%   \begin{verbatim}
%     *************************************************
%     * <text>
%     *************************************************
%   \end{verbatim}
%   where the \meta{text} will be wrapped to fit within the current
%   line length. 
% \end{function}
%
% \section{Kernel-specific functions}
%
% Messages from \LaTeX3 itself are handled by the general message system,
% but have their own functions. This allows some text to be pre-defined,
% and also ensures that serious errors can be handled properly.
%
% \begin{function}{\msg_kernel_new:nnnn, \msg_kernel_new:nnn}
%   \begin{syntax}
%     \cs{msg_kernel_new:nnnn} \Arg{module} \Arg{message} \Arg{text}
%     ~~\Arg{more text}
%   \end{syntax}
%   Creates a kernel \meta{message} for a given \meta{module}.
%   The message will be defined to first give \meta{text} and then
%   \meta{more text} if the user requests it. If no \meta{more text} is
%   available then a standard text is given instead. Within \meta{text}
%   and \meta{more text} four parameters (|#1| to |#4|) can be used:
%   these will be supplied at the time the message is used. The
%   parameters will be expanded when the message is used. Within the
%   \meta{text} and \meta{more text} |\\| can be used to start a new
%   line. An error will be raised if the \meta{message} already exists.
% \end{function}
%
% \begin{function}{\msg_kernel_set:nnnn, \msg_kernel_set:nnn}
%   \begin{syntax}
%     \cs{msg_kernel_set:nnnn} \Arg{module} \Arg{message} \Arg{text}
%     ~~\Arg{more text}
%   \end{syntax}
%   Sets up the text for a kernel \meta{message} for a given \meta{module}.
%   The message will be defined to first give \meta{text} and then
%   \meta{more text} if the user requests it. If no \meta{more text} is
%   available then a standard text is given instead. Within \meta{text}
%   and \meta{more text} four parameters (|#1| to |#4|) can be used:
%   these will be supplied at the time the message is used. The
%   parameters will be expanded when the message is used. Within the
%   \meta{text} and \meta{more text} |\\| can be used to start a new
%   line.
% \end{function}
%
% \begin{function}
%   {
%     \msg_kernel_fatal:nnxxxx ,
%     \msg_kernel_fatal:nnxxx  ,
%     \msg_kernel_fatal:nnxx   ,
%     \msg_kernel_fatal:nnx    ,
%     \msg_kernel_fatal:nn
%   }
%   \begin{syntax}
%     \cs{msg_kernel_fatal:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%       ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Issues kernel \meta{module} error \meta{message}, passing \meta{arg one}
%   to \meta{arg four} to the text-creating functions. After issuing a
%   fatal error the \TeX{} run will halt. Cannot be redirected.
% \end{function}
%
% \begin{function}
%   {
%     \msg_kernel_error:nnxxxx ,
%     \msg_kernel_error:nnxxx  ,
%     \msg_kernel_error:nnxx   ,
%     \msg_kernel_error:nnx    ,
%     \msg_kernel_error:nn
%   }
%   \begin{syntax}
%     \cs{msg_kernel_error:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%      ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Issues kernel \meta{module} error \meta{message}, passing \meta{arg one}
%   to
%   \meta{arg four} to the text-creating functions. The error will
%   stop processing and issue the text at the terminal. After user input,
%   the run will continue. Cannot be redirected.
% \end{function}
%
%  \begin{function}
%    {
%      \msg_kernel_warning:nnxxxx ,
%      \msg_kernel_warning:nnxxx  ,
%      \msg_kernel_warning:nnxx   ,
%      \msg_kernel_warning:nnx    ,
%      \msg_kernel_warning:nn
%    }
%    \begin{syntax}
%      \cs{msg_kernel_warning:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%       ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%    \end{syntax}
%    Issues kernel \meta{module} warning \meta{message}, passing
%    \meta{arg one} to
%    \meta{arg four} to the text-creating functions. The warning text
%    will be added to the log file, but the \TeX{} run will not be
%    interrupted.
%  \end{function}
%
% \begin{function}
%   {
%     \msg_kernel_info:nnxxxx ,
%     \msg_kernel_info:nnxxx  ,
%     \msg_kernel_info:nnxx   ,
%     \msg_kernel_info:nnx    ,
%     \msg_kernel_info:nn
%   }
%   \begin{syntax}
%     \cs{msg_kernel_info:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one}
%      ~~\Arg{arg two} \Arg{arg three} \Arg{arg four}
%   \end{syntax}
%   Issues kernel \meta{module} information \meta{message}, passing
%   \meta{arg one} to \meta{arg four} to the text-creating functions.
%   The information text will be added to the log file.
% \end{function}
%
% \section{Expandable errors}
%
% In a few places, the \LaTeX3 kernel needs to produce errors in an
% expansion only context. This must be handled very differently from
% normal error messages, as none of the tools to print to the terminal
% or the log file are expandable.
%
% \begin{function}{\msg_expandable_error:n}
%   \begin{syntax}
%     \cs{msg_expandable_error:n} \Arg{error message}
%   \end{syntax}
%   Issues an \enquote{Undefined error} message from \TeX{} itself,
%   and prints the \meta{error message}. The \meta{error message}
%   must be short: it is cropped at the end of one line.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3msg} implementation}
%
%    \begin{macrocode}
%<*initex|package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage
  {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
\package_check_loaded_expl:
%</package>
%    \end{macrocode}
%    
% \begin{variable}{\l_msg_tmp_tl}
%   A general scratch for the module.
%    \begin{macrocode}
\tl_new:N \l_msg_tmp_tl
%    \end{macrocode}
% \end{variable}
%
%\section{Creating messages}
%
% Messages are created and used separately, so there two parts to
% the code here. First, a mechanism for creating message text.
% This is pretty simple, as there is not actually a lot to do.
%
%\begin{variable}{\c_msg_text_prefix_tl, \c_msg_more_text_prefix_tl}
%   Locations for the text of messages.
%    \begin{macrocode}
\tl_const:Nn \c_msg_text_prefix_tl      { msg~text~>~ }
\tl_const:Nn \c_msg_more_text_prefix_tl { msg~extra~text~>~ }
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\msg_new:nnnn, \msg_new:nnn}
% \begin{macro}{\msg_set:nnnn, \msg_set:nnn}
%   Setting a message simply means saving the appropriate text
%   into two functions. A sanity check first.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_new:nnnn #1#2
  {
    \cs_if_exist:cT { \c_msg_text_prefix_tl #1 / #2 }
      {
        \msg_kernel_error:nn { msg } { message-already-defined }
          {#1} {#2}
      }
    \msg_set:nnnn {#1} {#2}
  }
\cs_new_protected:Npn \msg_new:nnn #1#2#3
  { \msg_new:nnnn {#1} {#2} {#3} { } }
\cs_new_protected:Npn \msg_set:nnnn #1#2#3#4
  {
    \cs_set:cpn { \c_msg_text_prefix_tl #1 / #2 }
      ##1##2##3##4 {#3}
    \cs_set:cpn { \c_msg_more_text_prefix_tl #1 / #2 }
      ##1##2##3##4 {#4}
  }
\cs_new_protected:Npn \msg_set:nnn #1#2#3
  { \msg_set:nnnn {#1} {#2} {#3} { } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Messages: support functions and text}
%
% \begin{variable}
%   {
%     \c_msg_coding_error_text_tl ,
%     \c_msg_continue_text_tl     ,
%     \c_msg_critical_text_tl     ,
%     \c_msg_fatal_text_tl        ,
%     \c_msg_help_text_tl         ,
%     \c_msg_no_info_text_tl      ,
%     \c_msg_on_line_tl           ,
%     \c_msg_return_text_tl       ,
%     \c_msg_trouble_text_tl
%   }
% Simple pieces of text for messages.
%    \begin{macrocode}
\tl_const:Nn \c_msg_coding_error_text_tl
  {
    This~is~a~coding~error.
    \\ \\
  }
\tl_const:Nn \c_msg_continue_text_tl
  { Type~<return>~to~continue }
\tl_const:Nn \c_msg_critical_text_tl
  { Reading~the~current~file~will~stop }
\tl_const:Nn \c_msg_fatal_text_tl
  { This~is~a~fatal~error:~LaTeX~will~abort }
\tl_const:Nn \c_msg_help_text_tl
  { For~immediate~help~type~H~<return> }
\tl_const:Nn \c_msg_no_info_text_tl
  {
    LaTeX~does~not~know~anything~more~about~this~error,~sorry.
    \c_msg_return_text_tl
  }
\tl_const:Nn \c_msg_on_line_text_tl { on~line }
\tl_const:Nn \c_msg_return_text_tl
  {
    \\ \\
    Try~typing~<return>~to~proceed.
    \\
    If~that~doesn't~work,~type~X~<return>~to~quit.
  }
\tl_const:Nn \c_msg_trouble_text_tl
  {
    \\ \\
    More~errors~will~almost~certainly~follow: \\
    the~LaTeX~run~should~be~aborted.
  }
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\msg_newline:, \msg_two_newlines:}
%   New lines are printed in the same way as for low-level file writing.
%    \begin{macrocode}
\cs_new_nopar:Npn \msg_newline: { ^^J }
\cs_new_nopar:Npn \msg_two_newlines: { ^^J ^^J }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\msg_line_number:}
% \begin{macro}{\msg_line_context:}
%   For writing the line number nicely.
%    \begin{macrocode}
\cs_new_nopar:Npn \msg_line_number: { \int_use:N \tex_inputlineno:D }
\cs_set_nopar:Npn \msg_line_context:
  {
    \c_msg_on_line_text_tl
    \c_space_tl
    \msg_line_number:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Showing messages: low level mechanism}
%
% \begin{variable}{\c_msg_hide_tl}
% \begin{variable}[aux]{\c_msg_hide_tl<dots>}
%   An empty variable with a number of (category code 11) periods at the
%   end of its name. This is used to push the \TeX{} part of an error
%   message \enquote{off the screen}. Using two variables here means that
%   later life is a little easier.
%    \begin{macrocode}
\char_set_catcode_letter:N \.
\tl_new:N
  \c_msg_hide_tl..........................................................
\tl_const:Nn \c_msg_hide_tl
 { \c_msg_hide_tl.......................................................... }
\char_set_catcode_other:N \.
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
% \begin{macro}{\msg_interrupt:xxx}
% \begin{macro}[aux]{\msg_interrupt_no_details:xx}
% \begin{macro}[aux]{\msg_interrupt_details:xxx}
% \begin{macro}[aux]{\msg_interrupt_text:n}
% \begin{macro}[aux]{\msg_interrupt_more_text:n}
% \begin{macro}[aux]{\msg_interrupt_aux:}
%   The low-level interruption macro is rather opaque, unfortunately. The
%   idea here is to create a a message which hides all of \TeX{}'s own
%   information by filling the output up with dots. To achieve this,
%   dots have to be letters. The odd
%   \cs{c_msg_hide_tl<dots>} actually does the hiding: it is the
%   large run of dots in the name that is important here. The meaning
%   of |\\| is altered so that the explanation text is a simple run
%   whilst the initial error has line-continuation shown.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_interrupt:xxx #1#2#3
  {
    \group_begin:
      \tl_if_empty:nTF {#3}
        { \msg_interrupt_no_details:xx {#1} {#2} }
        { \msg_interrupt_details:xxx {#1} {#2} {#3} }
      \msg_interrupt_aux:
    \group_end:
  }
%    \end{macrocode}
%    \begin{macrocode}
% Depending on the availability of more information there is a choice of
% how to set up the further help. The extra help text has to be set
% before the message itself can be issued. Everything is done using
% \texttt{x}-type expansion as the new line markers are different for
% the two type of text and need to be correctly set up.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_interrupt_no_details:xx #1#2
  {
    \iow_wrap:xnnnN
      { \\ \c_msg_no_info_text_tl }
      { |~ } { 2 } { } \msg_interrupt_more_text:n
    \iow_wrap:xnnnN { #1 \\ \\ #2 \\ \\ \c_msg_continue_text_tl }
      { ! ~ } { 2 } {} \msg_interrupt_text:n
  }
\cs_new_protected:Npn \msg_interrupt_details:xxx #1#2#3
  {
    \iow_wrap:xnnnN
      { \\ #3 }
      { |~ } { 2 } { } \msg_interrupt_more_text:n
    \iow_wrap:xnnnN { #1 \\ \\ #2 \\ \\ \c_msg_help_text_tl }
      { ! ~ } { 2 } { } \msg_interrupt_text:n
  }
\cs_new_protected:Npn \msg_interrupt_text:n #1
  { \tl_set:Nn \l_msg_text_tl {#1} }
\cs_new_protected:Npn \msg_interrupt_more_text:n #1
  {
%<*initex>
    \tl_set:Nx \l_msg_tmp_tl
%</initex>
%<*package>
    \protected@edef \l_msg_tmp_tl
%</package>
    {
      |'''''''''''''''''''''''''''''''''''''''''''''''
      #1
      \msg_newline:
      |...............................................
    }
    \tex_errhelp:D \exp_after:wN { \l_msg_tmp_tl }
  }
%    \end{macrocode}
%   The business end of the process starts by producing some visual
%   separation of the message from the main part of the log. It then
%   adds the hiding text to the message to print. The error message needs
%   to be printed with everything made \enquote{invisible}: this is where
%   the strange business with |&| comes in: this is made into another
%   |!|. There is also a closing brace that will show up in the output,
%   which is turned into a blank space.
%    \begin{macrocode}
\group_begin: % {
  \char_set_lccode:w `\} = `\  \scan_stop:
  \char_set_lccode:w `\& = `\! \scan_stop:
  \char_set_catcode_active:N \&
\tl_to_lowercase:n
  {
    \group_end:
    \cs_new_protected:Npn \msg_interrupt_aux:
      {
        \iow_term:x
          {
            \iow_newline:
            !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            \iow_newline:
            !
          }
        \tl_put_right:No \l_msg_text_tl { \c_msg_hide_tl }
        \cs_set_protected_nopar:Npx &
          { \tex_errmessage:D { \exp_not:o { \l_msg_text_tl } } }
        &
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\msg_log:x}
% \begin{macro}{\msg_term:x}
%   Printing to the log or terminal without a stop is rather easier.
%   A bit of simple visual work sets things off nicely.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_log:x #1
  {
    \iow_log:x { ................................................. }
    \iow_wrap:xnnnN { . ~ #1} { . ~ } { 2 } { }
      \iow_log:x
    \iow_log:x { ................................................. }
  }
\cs_new_protected:Npn \msg_term:x #1
  {
    \iow_term:x { ************************************************* }
    \iow_wrap:xnnnN { * ~ #1} { * ~ } { 2 } { }
      \iow_term:x
    \iow_term:x { ************************************************* }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \subsection{Displaying messages}
%
% \LaTeX{} is handling error messages and so the \TeX{} ones are disabled.
%    \begin{macrocode}
\int_set:Nn \tex_errorcontextlines:D { -1 }
%    \end{macrocode}
%
% \begin{macro}
%   {
%     \msg_fatal_text:n    ,
%     \msg_critical_text:n ,
%     \msg_error_text:n    ,
%     \msg_warning_text:n  ,
%     \msg_info_text:n
%   }
%   A function for issuing messages: both the text and order could
%   in principal vary.
%    \begin{macrocode}
\cs_new_nopar:Npn \msg_fatal_text:n #1 { Fatal~#1~error }
\cs_new_nopar:Npn \msg_critical_text:n #1 { Critical~#1~error }
\cs_new_nopar:Npn \msg_error_text:n #1 { #1~error }
\cs_new_nopar:Npn \msg_warning_text:n #1 { #1~warning }
\cs_new_nopar:Npn \msg_info_text:n #1 { #1~info }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\msg_see_documentation_text:n}
%   Contextual footer information.
%    \begin{macrocode}
\cs_new_nopar:Npn \msg_see_documentation_text:n #1
  { \\ \\ See~the~#1~documentation~for~further~information. }
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\l_msg_redirect_classes_prop, \l_msg_redirect_names_prop}
%   For filtering messages, a list of all messages and of those which have
%   to be modified is required.
%    \begin{macrocode}
\prop_new:N \l_msg_redirect_classes_prop
\prop_new:N \l_msg_redirect_names_prop
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\msg_class_set:nn}
%  Setting up a message class does two tasks. Any existing redirection
%  is cleared, and the various message functions are created
%  to simply use the code stored for the message.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \msg_class_set:nn #1#2
  {
    \prop_clear_new:c { l_msg_redirect_ #1 _prop }
    \cs_set_protected:cpn { msg_ #1 :nnxxxx } ##1##2##3##4##5##6
      { \msg_use:nnnnxxxx {#1} {#2} {##1} {##2} {##3} {##4} {##5} {##6} }
    \cs_set_protected:cpx { msg_ #1 :nnxxx } ##1##2##3##4##5
      { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} {##5} { } }
    \cs_set_protected:cpx { msg_ #1 :nnxx } ##1##2##3##4
      { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} { } { } }
    \cs_set_protected:cpx { msg_ #1 :nnx } ##1##2##3
      { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} { } { } { } }
    \cs_set_protected:cpx { msg_ #1 :nn } ##1##2
      { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} { } { } { } { } }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[pTF]{\msg_if_more_text:N, \msg_if_more_text:c}
% \begin{macro}[aux]{\msg_no_more_text:xxxx}
%   A test to see if any more text is available, using a
%   permanently-empty text function.
%    \begin{macrocode}
\prg_set_conditional:Npnn \msg_if_more_text:N #1 { p , T , F , TF }
  {
    \cs_if_eq:NNTF #1 \msg_no_more_text:xxxx
      { \prg_return_false:  }
      { \prg_return_true: }
  }
\cs_new:Npn \msg_no_more_text:xxxx #1#2#3#4 { }
\cs_generate_variant:Nn \msg_if_more_text_p:N { c }
\cs_generate_variant:Nn \msg_if_more_text:NT  { c }
\cs_generate_variant:Nn \msg_if_more_text:NF  { c }
\cs_generate_variant:Nn \msg_if_more_text:NTF { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%\begin{macro}
%  {
%    \msg_fatal:nnxxxx ,
%    \msg_fatal:nnxxx  ,
%    \msg_fatal:nnxx   ,
%    \msg_fatal:nnx    ,
%    \msg_fatal:nn
%  }
%   For fatal errors, after the error message \TeX{} bails out.
%    \begin{macrocode}
\msg_class_set:nn { fatal }
  {
    \msg_interrupt:xxx
      { \msg_fatal_text:n {#1} : ~ "#2" }
      {
        \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
        \msg_see_documentation_text:n {#1}
      }
      { \c_msg_fatal_text_tl }
    \tex_end:D
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \msg_critical:nnxxxx ,
%     \msg_critical:nnxxx  ,
%     \msg_critical:nnxx   ,
%     \msg_critical:nnx    ,
%     \msg_critical:nn
%  }
%   Not quite so bad: just end the current file.
%    \begin{macrocode}
\msg_class_set:nn { critical }
  {
    \msg_interrupt:xxx
      { \msg_critical_text:n {#1} : ~ "#2" }
      {
        \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
        \msg_see_documentation_text:n {#1}
      }
      { \c_msg_critical_text_tl }
    \tex_endinput:D
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \msg_error:nnxxxx ,
%     \msg_error:nnxxx  ,
%     \msg_error:nnxx   ,
%     \msg_error:nnx    ,
%     \msg_error:nn
%   }
%   For an error, the interrupt routine is called, then any recovery code
%   is tried.
%    \begin{macrocode}
\msg_class_set:nn { error }
  {
    \msg_if_more_text:cTF { \c_msg_more_text_prefix_tl #1 / #2 }
      {
        \msg_interrupt:xxx
          { \msg_error_text:n {#1} : ~ "#2" }
          {
            \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
            \msg_see_documentation_text:n {#1}
          }
          { \use:c { \c_msg_more_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} }
     }
     {
        \msg_interrupt:xxx
          { \msg_error_text:n {#1} : ~ "#2" }
          {
            \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
            \msg_see_documentation_text:n {#1}
          }
          { }
     }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \msg_warning:nnxxxx ,
%     \msg_warning:nnxxx  ,
%     \msg_warning:nnxx   ,
%     \msg_warning:nnx    ,
%     \msg_warning:nn
%   }
%   Warnings are printed to the terminal.
%    \begin{macrocode}
\msg_class_set:nn { warning }
  {
    \msg_term:x
      {
        \msg_warning_text:n {#1} : ~ "#2" \\ \\
        \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \msg_info:nnxxxx ,
%     \msg_info:nnxxx  ,
%     \msg_info:nnxx   ,
%     \msg_info:nnx    ,
%     \msg_info:nn
%   }
%   Information only goes into the log.
%    \begin{macrocode}
\msg_class_set:nn { info }
  {
    \msg_log:x
      {
        \msg_info_text:n {#1} : ~ "#2" \\ \\
        \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \msg_log:nnxxxx ,
%     \msg_log:nnxxx  ,
%     \msg_log:nnxx   ,
%     \msg_log:nnx    ,
%     \msg_log:nn
%   }
%   \enquote{Log} data is very similar to information, but with no extras
%   added.
%    \begin{macrocode}
\msg_class_set:nn { log }
  {
    \msg_log:x
      { \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \msg_none:nnxxxx ,
%     \msg_none:nnxxx  ,
%     \msg_none:nnxx   ,
%     \msg_none:nnx    ,
%     \msg_none:nn
%   }
%   The \texttt{none} message type is needed so that input can be gobbled.
%    \begin{macrocode}
\msg_class_set:nn { none } { }
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}
%   {
%     \l_msg_redirect_classes_seq ,
%     \l_msg_class_tl             ,
%     \l_msg_current_class_tl     ,
%     \l_msg_current_module_tl
% }
%   Support variables needed for the redirection system.
%    \begin{macrocode}
\seq_new:N \l_msg_redirect_classes_seq
\tl_new:N \l_msg_class_tl
\tl_new:N \l_msg_current_class_tl
\tl_new:N \l_msg_current_module_tl
%    \end{macrocode}
%\end{variable}
%
% \begin{macro}[int]{\msg_use:nnnnxxxx}
% \begin{macro}[aux]{\msg_use_aux:nnn}
% \begin{macro}[aux]{\msg_use_aux:nn}
% \begin{macro}[aux]{\msg_use_loop_check:nn}
% \begin{macro}[aux]{\msg_use_code:}
% \begin{macro}[aux]{\msg_use_loop:n, \msg_use_loop:o}
%   The main message-using macro creates two auxiliary functions: one
%   containing the code for the message, and the second a loop function.
%   There is then a hand-off to the system for checking if redirection is
%   needed.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_use:nnnnxxxx #1#2#3#4#5#6#7#8
  {
    \cs_set_protected_nopar:Npx \msg_use_code:
      {
        \seq_clear:N \exp_not:N \l_msg_redirect_classes_seq
        \exp_not:n {#2}
      }
    \cs_set_protected:Npx \msg_use_loop:n ##1
      {
        \seq_if_in:NnTF \exp_not:n \l_msg_redirect_classes_seq {#1}
          { \msg_kernel_error:nn { msg }  { message-loop } {#1} }
          {
            \seq_put_right:Nn \exp_not:N \l_msg_redirect_classes_seq {#1}
            \exp_not:N \cs_if_exist:cTF { msg_ ##1 :nnxxxx }
              {
                \exp_not:N \use:c { msg_ ##1 :nnxxxx }
                  \exp_not:n { {#3} {#4} {#5} {#6} {#7} {#8} }
              }
              {
                \msg_kernel_error:nnx { msg } { message-class-unknown } {##1}
              }
          }
      }
    \cs_if_exist:cTF { \c_msg_text_prefix_tl #3 / #4 }
      { \msg_use_aux:nnn {#1} {#3} {#4} }
      { \msg_kernel_error:nnxx { msg } { message-unknown } {#3} {#4} }
  }
%    \end{macrocode}
%   The first auxiliary macro looks for a match by name: the most
%   restrictive check.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \msg_use_aux:nnn #1#2#3
  {
    \tl_set:Nn \l_msg_current_class_tl  {#1}
    \tl_set:Nn \l_msg_current_module_tl {#2}
    \prop_if_in:NnTF \l_msg_redirect_names_prop { // #2 / #3 / }
      { \msg_use_loop_check:nn { names } { // #2 / #3 / } }
      { \msg_use_aux:nn {#1} {#2} }
  }
%    \end{macrocode}
%   The second function checks for general matches by module or for
%   all modules.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \msg_use_aux:nn #1#2
  {
    \prop_if_in:cnTF { l_msg_redirect_ #1 _prop } {#2}
      { \msg_use_loop_check:nn {#1} {#2} }
      {
        \prop_if_in:cnTF { l_msg_redirect_ #1 _prop } { * }
          { \msg_use_loop_check:nn {#1} { * } }
          { \msg_use_code: }
      }
  }
%    \end{macrocode}
%   When checking whether to loop, the same code is needed in a few
%   places.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_use_loop_check:nn #1#2
  {
    \prop_get:cnN { l_msg_redirect_ #1 _prop } {#2} \l_msg_class_tl
    \tl_if_eq:NNTF \l_msg_current_class_tl \l_msg_class_tl
      {
        { \msg_use_code: }
        { \msg_use_loop:o \l_msg_class_tl }
      }
  }
\cs_new_protected_nopar:Npn \msg_use_code: { }
\cs_new_protected:Npn \msg_use_loop:n #1 { }
\cs_generate_variant:Nn \msg_use_loop:n { o }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\msg_redirect_class:nn}
%   Converts class one into class two.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \msg_redirect_class:nn #1#2
  { \prop_put:cnn { l_msg_redirect_ #1 _prop } { * } {#2} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\msg_redirect_module:nnn}
%   For when all messages of a class should be altered for a given module.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \msg_redirect_module:nnn #1#2#3
  { \prop_put:cnn { l_msg_redirect_ #2 _prop } {#1} {#3} }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\msg_redirect_name:nnn}
%   Named message will always use the given class.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \msg_redirect_name:nnn #1#2#3
  { \prop_put:Nnn \l_msg_redirect_names_prop { // #1 / #2 / } {#3} }
%    \end{macrocode}
%\end{macro}
%
% \subsection{Kernel-specific functions}
%
% \begin{macro}{\msg_kernel_new:nnnn}
% \begin{macro}{\msg_kernel_new:nnn}
% \begin{macro}{\msg_kernel_set:nnnn}
% \begin{macro}{\msg_kernel_set:nnn}
%   The kernel needs some messages of its own. These are created using
%   pre-built functions. Two functions are provided: one more general
%   and one which only has the short text part.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \msg_kernel_new:nnnn #1#2
  { \msg_new:nnnn { LaTeX } { #1 / #2 } }
\cs_new_protected_nopar:Npn \msg_kernel_new:nnn #1#2
  { \msg_new:nnn { LaTeX } { #1 / #2 } }
\cs_new_protected_nopar:Npn \msg_kernel_set:nnnn #1#2
  { \msg_set:nnnn { LaTeX } { #1 / #2 } }
\cs_new_protected_nopar:Npn \msg_kernel_set:nnn #1#2
  { \msg_set:nnn { LaTeX } { #1 / #2 } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\msg_kernel_fatal:nnxxxx}
% \begin{macro}{\msg_kernel_fatal:nnxxx}
% \begin{macro}{\msg_kernel_fatal:nnxx}
% \begin{macro}{\msg_kernel_fatal:nnx}
% \begin{macro}{\msg_kernel_fatal:nn}
%   Fatal kernel errors cannot be re-defined.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_kernel_fatal:nnxxxx #1#2#3#4#5#6
  {
    \msg_interrupt:xxx
      { \msg_fatal_text:n { LaTeX } : ~ "#1 / #2" }
      {
        \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
          {#3} {#4} {#5} {#6}
        \msg_see_documentation_text:n { LaTeX3 }
      }
      { \c_msg_fatal_text_tl }
    \tex_end:D
  }
\cs_new_protected:Npn \msg_kernel_fatal:nnxxx #1#2#3#4#5
  {\msg_kernel_fatal:nnxxxx {#1} {#2} {#3} {#4} {#5} { } }
\cs_new_protected:Npn \msg_kernel_fatal:nnxx #1#2#3#4
  { \msg_kernel_fatal:nnxxxx {#1} {#2} {#3} {#4} { } { } }
\cs_new_protected:Npn \msg_kernel_fatal:nnx #1#2#3
  { \msg_kernel_fatal:nnxxxx {#1} {#2} {#3} { } { } { } }
\cs_new_protected:Npn \msg_kernel_fatal:nn #1#2
  { \msg_kernel_fatal:nnxxxx {#1} {#2} { } { } { } { } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\msg_kernel_error:nnxxxx}
% \begin{macro}{\msg_kernel_error:nnxxx}
% \begin{macro}{\msg_kernel_error:nnxx}
% \begin{macro}{\msg_kernel_error:nnx}
% \begin{macro}{\msg_kernel_error:nn}
% Neither can kernel errors.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_kernel_error:nnxxxx #1#2#3#4#5#6
  {
    \msg_if_more_text:cTF { \c_msg_more_text_prefix_tl LaTeX / #1 / #2 }
      {
        \msg_interrupt:xxx
          { \msg_error_text:n { LaTeX } : ~ " #1 / #2 " }
          {
            \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
              {#3} {#4} {#5} {#6}
            \msg_see_documentation_text:n { LaTeX3 }
          }
          {
            \use:c { \c_msg_more_text_prefix_tl LaTeX / #1 / #2 }
              {#3} {#4} {#5} {#6}
          }
      }
      {
        \msg_interrupt:xxx
          { \msg_error_text:n { LaTeX } : ~ " #1 / #2 " }
          {
            \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
              {#3} {#4} {#5} {#6}
            \msg_see_documentation_text:n { LaTeX3 }
          }
          { }
      }
  }
\cs_new_protected:Npn \msg_kernel_error:nnxxx #1#2#3#4#5
  {\msg_kernel_error:nnxxxx {#1} {#2} {#3} {#4} {#5} { } }
\cs_set_protected:Npn \msg_kernel_error:nnxx #1#2#3#4
  { \msg_kernel_error:nnxxxx {#1} {#2} {#3} {#4} { } { } }
\cs_set_protected:Npn \msg_kernel_error:nnx #1#2#3
  { \msg_kernel_error:nnxxxx {#1} {#2} {#3} { } { } { } }
\cs_set_protected:Npn \msg_kernel_error:nn #1#2
  { \msg_kernel_error:nnxxxx {#1} {#2} { } { } { } { } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\msg_kernel_warning:nnxxxx}
% \begin{macro}{\msg_kernel_warning:nnxxx}
% \begin{macro}{\msg_kernel_warning:nnxx}
% \begin{macro}{\msg_kernel_warning:nnx}
% \begin{macro}{\msg_kernel_warning:nn}
% \begin{macro}{\msg_kernel_info:nnxxxx}
% \begin{macro}{\msg_kernel_info:nnxxx}
% \begin{macro}{\msg_kernel_info:nnxx}
% \begin{macro}{\msg_kernel_info:nnx}
% \begin{macro}{\msg_kernel_info:nn}
%   Kernel messages which can be redirected.
%    \begin{macrocode}
\prop_new:N \l_msg_redirect_kernel_warning_prop
\cs_new_protected:Npn \msg_kernel_warning:nnxxxx #1#2#3#4#5#6
  {
    \msg_use:nnnnxxxx { warning }
      {
        \msg_term:x
          {
            \msg_warning_text:n { LaTeX } : ~ " #1 / #2 " \\ \\
            \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
              {#3} {#4} {#5} {#6}
          }
      }
      { LaTeX } { #1 / #2 } {#3} {#4} {#5} {#6}
  }
\cs_new_protected:Npn \msg_kernel_warning:nnxxx #1#2#3#4#5
  { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} {#4} {#5} { } }
\cs_new_protected:Npn \msg_kernel_warning:nnxx #1#2#3#4
  { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} {#4} { } { } }
\cs_new_protected:Npn \msg_kernel_warning:nnx #1#2#3
  { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} { } { } { } }
\cs_new_protected:Npn \msg_kernel_warning:nn #1#2
  { \msg_kernel_warning:nnxxxx {#1} {#2} { } { } { } { } }
\prop_new:N \l_msg_redirect_kernel_info_prop
\cs_new_protected:Npn \msg_kernel_info:nnxxxx #1#2#3#4#5#6
  {
    \msg_use:nnnnxxxx { info }
      {
        \msg_log:x
          {
            \msg_info_text:n { LaTeX } : ~ " #1 / #2 " \\ \\
            \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
              {#3} {#4} {#5} {#6}
          }
      }
      { LaTeX } { #1 / #2 } {#3} {#4} {#5} {#6}
  }
\cs_new_protected:Npn \msg_kernel_info:nnxxx #1#2#3#4#5
  { \msg_kernel_info:nnxxxx {#1} {#2} {#3} {#4} {#5} { } }
\cs_new_protected:Npn \msg_kernel_info:nnxx #1#2#3#4
  { \msg_kernel_info:nnxxxx {#1} {#2} {#3} {#4} { } { } }
\cs_new_protected:Npn \msg_kernel_info:nnx #1#2#3
  { \msg_kernel_info:nnxxxx {#1} {#2} {#3} { } { } { } }
\cs_new_protected:Npn \msg_kernel_info:nn #1#2
  { \msg_kernel_info:nnxxxx {#1} {#2} { } { } { } { } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% Error messages needed to actually implement the message system
% itself.
%    \begin{macrocode}
\msg_kernel_new:nnnn { msg } { message-already-defined }
  { Message~'#2'~for~module~'#1'~already~defined. }
  {
    \c_msg_coding_error_text_tl
    LaTeX~was~asked~to~define~a~new~message~called~'#2'
    by~the~module~'#1'~module:\\
    this~message~already~exists.
    \c_msg_return_text_tl
  }
\msg_kernel_new:nnnn { msg } { message-unknown }
  { Unknown~message~'#2'~for~module~'#1'. }
  {
    \c_msg_coding_error_text_tl
    LaTeX~was~asked~to~display~a~message~called~'#2'\\
    by~the~module~'#1'~module:~this~message~does~not~exist.
    \c_msg_return_text_tl
  }
\msg_kernel_new:nnnn { msg } { message-class-unknown }
  { Unknown~message~class~'#1'. }
  {
    LaTeX~has~been~asked~to~redirect~messages~to~a~class~'#1':\\
    this~was~never~defined.
    \c_msg_return_text_tl
  }
\msg_kernel_new:nnnn { msg } { redirect-loop }
  { Message~redirection~loop~for~message~class~'#1'. }
  {
    LaTeX~has~been~asked~to~redirect~messages~in~an~infinite~loop.\\
    The~original~message~here~has~been~lost.
    \c_msg_return_text_tl
  }
%    \end{macrocode}
% 
% Messages for earlier kernel modules.
%    \begin{macrocode}
\msg_kernel_new:nnnn { kernel } { bad-number-of-arguments }
  { Function~'#1'~cannot~be~defined~with~#2~arguments. }
  {
    \c_msg_coding_error_text_tl
    LaTeX~has~been~asked~to~define~a~function~'#1'~with~
    #2~arguments. \\
    TeX~allows~between~0~and~9~arguments~for~a~single~function.
  }
\msg_kernel_new:nnnn { kernel } { command-already-defined }
  { Control~sequence~#1~already~defined. }
  {
    \c_msg_coding_error_text_tl
    LaTeX~has~been~asked~to~create~a~new~control~sequence~'#1'~
    but~this~name~has~already~been~used~elsewhere. \\ \\
    The~current~meaning~is:\\
    \ \ #2
  }
\msg_kernel_new:nnnn { kernel } { command-not-defined }
  { Control~sequence~#1~undefined. }
  {
    \c_msg_coding_error_text_tl
    LaTeX~has~been~asked~to~use~a~command~#1,~but~this~has~not~
    been~defined~yet.
  }
\msg_kernel_new:nnnn { kernel } { variable-not-defined }
  { Variable~#1~undefined. }
  {
    \c_msg_coding_error_text_tl
    LaTeX~has~been~asked~to~show~a~variable~#1,~but~this~has~not~
    been~defined~yet.
  }
\msg_kernel_new:nnnn { seq } { empty-sequence }
  { Empty~sequence~#1. }
  {
    \c_msg_coding_error_text_tl
    LaTeX~has~been~asked~to~recover~an~entry~from~a~sequence~that~
    has~no~content:~that~cannot~happen!
  }
\msg_kernel_new:nnnn { tl } { empty-search-pattern }
  { Empty~search~pattern. }
  {
    \c_msg_coding_error_text_tl
    LaTeX~has~been~asked~to~replace~an~empty~pattern~by~'#1':~that~%
    would~lead~to~an~infinite~loop!
  }
%    \end{macrocode}
%
% \begin{macro}{\msg_kernel_bug:x}
% \begin{variable}{\c_msg_kernel_bug_text_tl, \c_msg_kernel_bug_more_text_tl}
% The \LaTeX{} coding bug error gets re-visited here.
%    \begin{macrocode}
\cs_set_protected:Npn \msg_kernel_bug:x #1
  {
    \msg_interrupt:xxx { \c_msg_kernel_bug_text_tl }
      {
        #1
       \msg_see_documentation_text:n { LaTeX3 }
      }
      { \c_msg_kernel_bug_more_text_tl }
  }
\tl_const:Nn \c_msg_kernel_bug_text_tl
  { This~is~a~LaTeX~bug:~check~coding! }
\tl_const:Nn \c_msg_kernel_bug_more_text_tl
  {
    There~is~a~coding~bug~somewhere~around~here. \\
    This~probably~needs~examining~by~an~expert.
    \c_msg_return_text_tl
  }
%    \end{macrocode}
% \end{variable}
% \end{macro}
%
% \subsection{Expandable errors}
%
% \begin{macro}{\msg_expandable_error:n}
%   
%    \begin{macrocode}
\group_begin:
\cs_new:Npx \msg_expandable_error:n #1
  {
    \exp_not:n
      {
        \exp_after:wN \exp_after:wN
        \exp_after:wN \use_none_delimit_by_q_stop:w
      }
    \exp_not:N \use:n { \exp_not:c { LaTeX3 ~ error : } #1 }
    \exp_not:N \q_stop
  }
\group_end:
%    \end{macrocode}
% \end{macro}
%
% \subsection{Deprecated functions}
%
% Deprecated on 2011-05-27, for removal by 2011-08-31.
%
% \begin{macro}{\msg_class_new:nn}
% This is only ever used in a |set| fashion.
%    \begin{macrocode}
\cs_new_eq:NN \msg_class_new:nn \msg_class_set:nn
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \msg_trace:nnxxxx, \msg_trace:nnxxx, \msg_trace:nnxx,
%     \msg_trace:nnx,    \msg_trace:nn
%   }
%   The performance here is never going to be good enough for tracing
%   code, so let's be realistic.
%    \begin{macrocode}
\cs_new_eq:NN \msg_trace:nnxxxx \msg_log:nnxxxx
\cs_new_eq:NN \msg_trace:nnxxx  \msg_log:nnxxx
\cs_new_eq:NN \msg_trace:nnxx   \msg_log:nnxx
\cs_new_eq:NN \msg_trace:nnx    \msg_log:nnx
\cs_new_eq:NN \msg_trace:nn     \msg_log:nn
%    \end{macrocode}
%\end{macro}
%
% \begin{macro}{\msg_generic_new:nnn}
% \begin{macro}{\msg_generic_new:nn}
% \begin{macro}{\msg_generic_set:nnn}
% \begin{macro}{\msg_generic_set:nn}
% \begin{macro}{\msg_direct_interrupt:xxxxx}
% \begin{macro}{\msg_direct_log:xx}
% \begin{macro}{\msg_direct_term:xx}
%  These were all too low-level.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_generic_new:nnn #1#2#3 { \deprecated }
\cs_new_protected:Npn \msg_generic_new:nn  #1#2   { \deprecated }
\cs_new_protected:Npn \msg_generic_set:nnn #1#2#3 { \deprecated }
\cs_new_protected:Npn \msg_generic_set:nn  #1#2   { \deprecated }
\cs_new_protected:Npn \msg_direct_interrupt:xxxxx #1#2#3#4#5 { \deprecated }
\cs_new_protected:Npn \msg_direct_log:xx #1#2  { \deprecated }
\cs_new_protected:Npn \msg_direct_term:xx #1#2 { \deprecated }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
