summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/expl3/l3msg.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-06-09 23:31:15 +0000
committerKarl Berry <karl@freefriends.org>2009-06-09 23:31:15 +0000
commit215b9a864d5829070bdc66ba736986eb72e5143e (patch)
treefe0882c81fc4ec945cee4b512f72eaa21ea5f791 /Master/texmf-dist/source/latex/expl3/l3msg.dtx
parentdf90ec06321940c2f066b05e12f1b5ab099105da (diff)
expl3 1407 (9jun09)
git-svn-id: svn://tug.org/texlive/trunk@13686 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3msg.dtx')
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3msg.dtx1336
1 files changed, 1336 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3msg.dtx b/Master/texmf-dist/source/latex/expl3/l3msg.dtx
new file mode 100644
index 00000000000..4eb211be1a6
--- /dev/null
+++ b/Master/texmf-dist/source/latex/expl3/l3msg.dtx
@@ -0,0 +1,1336 @@
+% \iffalse
+%% File: l3msg.dtx Copyright (C) 2009 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver|package>
+\RequirePackage{l3names}
+%</driver|package>
+%\fi
+\GetIdInfo$Id: l3msg.dtx 1362 2009-05-28 20:19:21Z joseph $
+ {L3 Experimental LaTeX Messages module}
+%\iffalse
+%<*driver>
+%\fi
+\ProvidesFile{\filename.\filenameext}
+ [\filedate\space v\fileversion\space\filedescription]
+%\iffalse
+\documentclass[full]{l3doc}
+\begin{document}
+\DocInput{l3msg.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3msg} package\thanks{This file
+% has version number \fileversion, last
+% revised \filedate.}\\
+% Communicating with the user}
+% \author{\Team}
+% \date{\filedate}
+% \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. Inside the
+% message text, spaces are \emph{not} ignored. A space where \TeX\
+% would normally gobble one can be created using |\ |, and a new line
+% with |\\|. New lines may have ``continuation'' text added by the
+% output system.
+%
+%\begin{function}{
+% \msg_new:nnnnn|
+% \msg_new:nnnn|
+% \msg_new:nnn|
+% \msg_set:nnnnn|
+% \msg_set:nnnn|
+% \msg_set:nnn
+%}
+% \begin{syntax}
+% "\msg_new:nnnn" <module> <name> <text> <more text> <code>
+% \end{syntax}
+% Creates new message <name> for <module> to produce <text> initially,
+% <more text> if requested by the user and to insert <code> after the
+% message when used as an error. <text> and <more text> can use up to
+% two macro parameters (|#1| and |#2|), which are supplied by the
+% message system. Inside <text> and <more text> spaces are not ignored.
+%\end{function}
+%
+% \section{Message classes}
+%
+% Creating message output requires the message to be given a class.
+%
+%\begin{function}{
+% \msg_class_new:nn|
+% \msg_class_set:nn
+%}
+% \begin{syntax}
+% "\msg_class_new:nn" <class> <code>
+% \end{syntax}
+% Creates new <class> to output a message, using <code> to process
+% the message text.
+%\end{function}
+%
+% The module defines several common message classes. The following
+% describes the standard behaviour of each class if no redirection of
+% the class or message is active.
+%
+%\begin{function}{
+% \msg_fatal:nnxx|
+% \msg_fatal:nnx|
+% \msg_fatal:nn
+%}
+% \begin{syntax}
+% "\msg_fatal:nnxx" <module> <name> <arg one> <arg two>
+% \end{syntax}
+% Issues <module> error message <name>, passing <arg one> and
+% <arg two> to the text-creating functions. The \TeX\ run then halts.
+%\end{function}
+%
+%\begin{function}{
+% \msg_error:nnxx|
+% \msg_error:nnx|
+% \msg_error:nn
+%}
+% \begin{syntax}
+% "\msg_error:nnxx" <module> <name> <arg one> <arg two>
+% \end{syntax}
+% Issues <module> error message <name>, passing <arg one> and
+% <arg two> to the text-creating functions.
+% \begin{texnote}
+% The standard output here is similar to \cs{PackageError}.
+% \end{texnote}
+%\end{function}
+%
+%\begin{function}{
+% \msg_warning:nnxx|
+% \msg_warning:nnx|
+% \msg_warning:nn
+%}
+% \begin{syntax}
+% "\msg_warning:nnxx" <module> <name> <arg one> <arg two>
+% \end{syntax}
+% Prints <module> message <name> to the terminal, passing <arg one> and
+% <arg two> to the text-creating functions.
+% \begin{texnote}
+% The standard output here is similar to \cs{PackageWarningNoLine}.
+% \end{texnote}
+%\end{function}
+%
+%\begin{function}{
+% \msg_info:nnxx|
+% \msg_info:nnx|
+% \msg_info:nn
+%}
+% \begin{syntax}
+% "\msg_info:nnxx" <module> <name> <arg one> <arg two>
+% \end{syntax}
+% Prints <module> message <name> to the log, passing <arg one> and
+% <arg two> to the text-creating functions.
+% \begin{texnote}
+% The standard output here is similar to \cs{PackageInfoNoLine}.
+% \end{texnote}
+%\end{function}
+%
+%\begin{function}{
+% \msg_log:nnxx|
+% \msg_log:nnx|
+% \msg_log:nn
+%}
+% \begin{syntax}
+% "\msg_info:nnxx" <module> <name> <arg one> <arg two>
+% \end{syntax}
+% Prints <module> message <name> to the log, passing <arg one> and
+% <arg two> to the text-creating functions. No continuation text is
+% added.
+%\end{function}
+%
+%\begin{function}{
+% \msg_trace:nnxx|
+% \msg_trace:nnx|
+% \msg_trace:nn
+%}
+% \begin{syntax}
+% "\msg_info:nnxx" <module> <name> <arg one> <arg two>
+% \end{syntax}
+% Prints <module> message <name> to the log, passing <arg one> and
+% <arg two> to the text-creating functions. No continuation text is
+% added.
+%\end{function}
+%
+%\begin{function}{
+% \msg_none:nnxx|
+% \msg_none:nnx|
+% \msg_none:nn
+%}
+% \begin{syntax}
+% "\msg_none:nnxx" <module> <name> <arg one> <arg two>
+% \end{syntax}
+% Does nothing: used for redirecting other message classes.
+%\end{function}
+%
+% \section{Redirecting messages}
+%
+%\begin{function}{\msg_redirect_class:nn}
+% \begin{syntax}
+% "\msg_redirect_class:nn" <class one> <class two>
+% \end{syntax}
+% Redirect all messages of <class one> to appear as those of
+% <class two>.
+%\end{function}
+%
+%\begin{function}{\msg_redirect_module:nnn}
+% \begin{syntax}
+% "\msg_redirect_module:nnn" <class one> <module> <class two>
+% \end{syntax}
+% Redirect <module> messages of <class one> to appear in <class two>.
+% \begin{texnote}
+% This function can be used to make some messages ``silent'' by
+% default. For example, all of the \texttt{trace} messages of
+% <module> could be turned off with:
+% \begin{verbatim}
+% \msg_redirect_module:nnn { trace } { module } { none }
+% \end{verbatim}
+% \end{texnote}
+%\end{function}
+%
+%\begin{function}{\msg_redirect_name:nnn}
+% \begin{syntax}
+% "\msg_redirect_name:nnn" <module> <message> <class>
+% \end{syntax}
+% Redirect <module> <message> to appear using <class>.
+%\end{function}
+%
+% \section{Support functions for output}
+%
+%\begin{function}{\msg_line_context:}
+% \begin{syntax}
+% "\msg_line_context:"
+% \end{syntax}
+% Prints the current line number preceded by \cs{c_msg_on_line_tl}.
+%\end{function}
+%
+%\begin{function}{\msg_line_number:}
+% \begin{syntax}
+% "\msg_line_number:"
+% \end{syntax}
+% Prints the current line number.
+%\end{function}
+%
+%\begin{function}{
+% \msg_newline:|
+% \msg_two_newlines:
+%}
+% \begin{syntax}
+% "\msg_newline:"
+% \end{syntax}
+% Print one or two newlines with no continuation information.
+%\end{function}
+%
+%\begin{function}{
+% \msg_space:|
+% \msg_two_spaces:|
+% \msg_four_spaces:
+%}
+% \begin{syntax}
+% "\msg_space:"
+% \end{syntax}
+% Print one, two or four spaces: needed where a literal space would
+% otherwise be gobbled by \TeX.
+%\end{function}
+%
+% \section{Low-level functions}
+%
+% The low-level functions do not make assumptions about module names.
+% The output functions here produce messages directly, and do not
+% respond to redirection.
+%
+%\begin{function}{
+% \msg_generic_new:nnnn|
+% \msg_generic_new:nnn|
+% \msg_generic_new:nn|
+% \msg_generic_set:nnnn|
+% \msg_generic_set:nnn|
+% \msg_generic_set:nn
+%}
+% \begin{syntax}
+% "\msg_generic_new:nnnn" <name> <text> <more text> <code>
+% \end{syntax}
+% Creates new message <name> to produce <text> initially, <more text>
+% if requested by the user and to insert <code> after the message when
+% used as an error. <text> and <more text> can use up to two macro
+% parameters (|#1| and |#2|), which are supplied by the message system.
+% Inside <text> and <more text> spaces are not ignored.
+%\end{function}
+%
+%\begin{function}{\msg_direct_interrupt:xxxxn}
+% \begin{syntax}
+% "\msg_direct_interrupt:xxxxn" <first line> <text>
+% ~~~~<continuation> <more text> <code>
+% \end{syntax}
+% Executes a \TeX\ error, interrupting compilation. The <first line>
+% is displayed followed by <text> and the input prompt. <more text> is
+% displays if requested by the user, and <code> is inserted after the
+% message. If <more text> is blank a default is supplied. Each line of
+% <text> (broken with |\\|) begins with <continuation>.
+%\end{function}
+%
+%\begin{function}{
+% \msg_direct_log:xx|
+% \msg_direct_term:xx
+%}
+% \begin{syntax}
+% "\msg_direct_log:xx" <text> <continuation>
+% \end{syntax}
+% Prints <text> to either the log or terminal. New lines (broken
+% with |\\|) start with <continuation>.
+%\end{function}
+%
+% \section{Kernel-specific functions}
+%
+%\begin{function}{
+% \msg_kernel_new:nnnn|
+% \msg_kernel_new:nnn|
+% \msg_kernel_new:nn|
+% \msg_kernel_set:nnnn|
+% \msg_kernel_set:nnn|
+% \msg_kernel_set:nn
+%}
+% \begin{syntax}
+% "\msg_kernel_new:nnn" <name> <text> <more text> <code>
+% \end{syntax}
+% Creates new kernel message <name> to produce <text> initially,
+% <more text> if requested by the user and to insert <code> after the
+% message when used as an error. <text> and <more text> can use up to
+% two macro parameters (|#1| and |#2|), which are supplied by the
+% message system.
+%\end{function}
+%
+%\begin{function}{
+% \msg_kernel_fatal:nxx|
+% \msg_kernel_fatal:nx|
+% \msg_kernel_fatal:n
+%}
+% \begin{syntax}
+% "\msg_kernel_fatal:nxx" <name> <arg one> <arg two>
+% \end{syntax}
+% Issues kernel error message <name>, passing <arg one> and
+% <arg two> to the text-creating functions. The \TeX\ run then halts.
+% Cannot be redirected.
+%\end{function}
+%
+%\begin{function}{
+% \msg_kernel_error:nxx|
+% \msg_kernel_error:nx|
+% \msg_kernel_error:n
+%}
+% \begin{syntax}
+% "\msg_kernel_error:nxx" <name> <arg one> <arg two>
+% \end{syntax}
+% Issues kernel error message <name>, passing <arg one> and
+% <arg two> to the text-creating functions. Cannot be redirected.
+%\end{function}
+%
+%\begin{function}{
+% \msg_kernel_warning:nxx|
+% \msg_kernel_warning:nx|
+% \msg_kernel_warning:n
+%}
+% \begin{syntax}
+% "\msg_kernel_warning:nxx" <name> <arg one> <arg two>
+% \end{syntax}
+% Prints kernel message <name> to the terminal, passing <arg one> and
+% <arg two> to the text-creating functions.
+%\end{function}
+%
+%\begin{function}{
+% \msg_kernel_info:nxx|
+% \msg_kernel_info:nx|
+% \msg_kernel_info:n
+%}
+% \begin{syntax}
+% "\msg_kernel_info:nxx" <name> <arg one> <arg two>
+% \end{syntax}
+% Prints kernel message <name> to the log, passing <arg one> and
+% <arg two> to the text-creating functions.
+%\end{function}
+%
+%\begin{function}{\msg_kernel_bug:x}
+% \begin{syntax}
+% "\msg_kernel_bug:x" <text>
+% \end{syntax}
+% Short-cut for ``This is a LaTeX bug: check coding'' errors.
+%\end{function}
+%
+% \section{Variables and constants}
+%
+%\begin{variable}{
+% \c_msg_fatal_tl|
+% \c_msg_error_tl|
+% \c_msg_warning_tl|
+% \c_msg_info_tl
+%}
+% Simple headers for errors.
+%\end{variable}
+%
+%\begin{variable}{
+% \c_msg_fatal_text_tl|
+% \c_msg_help_text_tl|
+% \c_msg_kernel_bug_text_tl|
+% \c_msg_kernel_bug_more_text_tl|
+% \c_msg_no_info_text_tl|
+% \c_msg_return_text_tl
+%}
+% Various pieces of text for use in messages, which are not changed by
+% the code here although they could be to alter the language.
+%\end{variable}
+%
+%\begin{variable}{\c_msg_on_line_tl}
+% The ``on line'' phrase for line numbers.
+%\end{variable}
+%
+%\begin{variable}{
+% \c_msg_text_prefix_tl|
+% \c_msg_more_text_prefix_tl|
+% \c_msg_code_prefix_tl
+%}
+% Header information for storing the ``paths'' to parts of a message.
+%\end{variable}
+%
+%\begin{variable}{
+% \l_msg_class_tl|
+% \l_msg_current_class_tl
+%}
+% Information about message method, used for filtering.
+%\end{variable}
+%
+%\begin{variable}{\l_msg_names_clist}
+% List of all of the message names defined.
+%\end{variable}
+%
+%\begin{variable}{
+% \l_msg_redirect_classes_prop|
+% \l_msg_redirect_names_prop
+%}
+% Re-direction lists containing the class of message to convert an
+% different one.
+%\end{variable}
+%
+%\begin{variable}{\l_msg_redirect_classes_clist}
+% List so that filtering does not loop.
+%\end{variable}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3msg} implementation}
+%
+% The usual lead-off.
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage
+ {\filename}{\filedate}{\fileversion}{\filedescription}
+\package_check_loaded_expl:
+%</package>
+%<*initex|package>
+% \end{macrocode}
+%
+% \LaTeX\ is handling context, so the \TeX\ ``noise'' is turned down.
+% \begin{macrocode}
+\int_set:Nn \tex_errorcontextlines:D { \c_minus_one }
+% \end{macrocode}
+%
+% \subsection{Variables and constants}
+%
+%\begin{macro}{\c_msg_fatal_tl}
+%\begin{macro}{\c_msg_error_tl}
+%\begin{macro}{\c_msg_warning_tl}
+%\begin{macro}{\c_msg_info_tl}
+% Header information.
+% \begin{macrocode}
+\tl_new:Nn \c_msg_fatal_tl { Fatal~Error }
+\tl_new:Nn \c_msg_error_tl { Error }
+\tl_new:Nn \c_msg_warning_tl { Warning }
+\tl_new:Nn \c_msg_info_tl { Info }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\c_msg_fatal_text_tl}
+%\begin{macro}{\c_msg_help_text_tl}
+%\begin{macro}{\c_msg_kernel_bug_text_tl}
+%\begin{macro}{\c_msg_kernel_bug_more_text_tl}
+%\begin{macro}{\c_msg_no_info_text_tl}
+%\begin{macro}{\c_msg_return_text_tl}
+% Simple pieces of text for messages.
+% \begin{macrocode}
+\tl_new:Nn \c_msg_fatal_text_tl {
+ This~is~a~fatal~error:~LaTeX~will~abort
+}
+\tl_new:Nn \c_msg_help_text_tl {
+ For~immediate~help~type~H~<return>
+}
+\tl_new:Nn \c_msg_kernel_bug_text_tl {
+ This~is~a~LaTeX~bug:~check~coding!
+}
+\tl_new:Nn \c_msg_kernel_bug_more_text_tl {
+ There~is~a~coding~bug~somewhere~around~here.
+ \msg_newline:
+ This~probably~needs~examining~by~an~expert.
+ \c_msg_return_text_tl
+}
+\tl_new:Nn \c_msg_no_info_text_tl {
+ LaTeX~does~not~know~anything~more~about~this~error,~sorry.
+ \c_msg_return_text_tl
+}
+\tl_new:Nn \c_msg_return_text_tl {
+ \msg_two_newlines:
+ Try~typing~<return>~to~proceed.
+ \msg_newline:
+ If~that~doesn't~work,~type~X~<return>~to~quit
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}[aux]{\c_msg_hide_tl<spaces>}
+% An empty variable with a number of (category code 11) spaces at the
+% end of its name. This is used to push the \TeX\ part of an error
+% message ``off the screen''.
+%
+% No indentation here as \verb*| | is a letter!
+% \begin{macrocode}
+\group_begin:
+\char_make_letter:N\ %
+\tl_to_lowercase:n{%
+\group_end:%
+\tl_new:Nn%
+\c_msg_hide_tl %
+{}%
+}%
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\c_msg_on_line_tl}
+% ``On line''.
+% \begin{macrocode}
+\tl_new:Nn \c_msg_on_line_tl { on~line }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\c_msg_text_prefix_tl}
+%\begin{macro}{\c_msg_more_text_prefix_tl}
+%\begin{macro}{\c_msg_code_prefix_tl}
+% Prefixes for storage areas.
+% \begin{macrocode}
+\tl_new:Nn \c_msg_text_prefix_tl { msg_text // }
+\tl_new:Nn \c_msg_more_text_prefix_tl { msg_text_more // }
+\tl_new:Nn \c_msg_code_prefix_tl { msg_code // }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_msg_class_tl}
+%\begin{macro}{\l_msg_current_class_tl}
+% For holding the current message method and that for redirection.
+% \begin{macrocode}
+\tl_new:N \l_msg_class_tl
+\tl_new:N \l_msg_current_class_tl
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_msg_names_clist}
+% Lists used for filtering.
+% \begin{macrocode}
+\clist_new:N \l_msg_names_clist
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_msg_redirect_classes_prop}
+%\begin{macro}{\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{macro}
+%\end{macro}
+%\begin{macro}{\l_msg_redirect_classes_clist}
+% To prevent an infinite loop.
+% \begin{macrocode}
+\clist_new:N \l_msg_redirect_classes_clist
+% \end{macrocode}
+%\end{macro}
+%
+% \subsection{Output helper functions}
+%
+%\begin{macro}{\msg_line_number:}
+%\begin{macro}{\msg_line_context:}
+% For writing the line number nicely.
+% \begin{macrocode}
+\cs_new_nopar:Nn { \msg_line_number: } {
+ \toks_use:N \tex_inputlineno:D
+}
+\cs_new_nopar:Nn { \msg_line_context: } {
+ \msg_space:
+ \c_msg_on_line_tl
+ \msg_space:
+ \msg_line_number:
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_newline:}
+%\begin{macro}{\msg_two_newlines:}
+% Always forces a new line.
+% \begin{macrocode}
+\cs_new_nopar:Nn \msg_newline: { ^^J }
+\cs_new_nopar:Nn \msg_two_newlines: { ^^J ^^J }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_space:}
+%\begin{macro}{\msg_two_spaces:}
+%\begin{macro}{\msg_four_spaces:}
+% For printing spaces, some very simple functions.
+% \begin{macrocode}
+\cs_new_nopar:Nn \msg_space: { ~ }
+\cs_new_nopar:Nn \msg_two_spaces: { \msg_space: \msg_space: }
+\cs_new_nopar:Nn \msg_four_spaces: { \msg_two_spaces: \msg_two_spaces: }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Generic functions}
+%
+% The lowest level functions make no assumptions about modules,
+% \emph{etc.}
+%
+%\begin{macro}{\msg_generic_new:nnnn}
+%\begin{macro}{\msg_generic_new:nnn}
+%\begin{macro}{\msg_generic_new:nn}
+% Creating a new message is basically the same as the non-checking
+% version, and so after a check everything hands over.
+% \begin{macrocode}
+\cs_new_nopar:Npn \msg_generic_new:nnnn #1 {
+ \exp_args:Nc \chk_if_free_cs:N { \c_msg_text_prefix_tl #1 :nn }
+ \msg_generic_set:nnnn {#1}
+}
+\cs_new_nopar:Npn \msg_generic_new:nnn #1 {
+ \exp_args:Nc \chk_if_free_cs:N { \c_msg_text_prefix_tl #1 :nn }
+ \msg_generic_set:nnn {#1}
+}
+\cs_new_nopar:Npn \msg_generic_new:nn #1 {
+ \exp_args:Nc \chk_if_free_cs:N { \c_msg_text_prefix_tl #1 :nn }
+ \msg_generic_set:nn {#1}
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_generic_set:nnnn}
+%\begin{macro}{\msg_generic_set:nnn}
+%\begin{macro}{\msg_generic_set:nn}
+%\begin{macro}[aux]{\msg_generic_set_clist:n}
+%\begin{macro}[aux]{\msg_generic_set_text:n}
+%\begin{macro}[aux]{\msg_generic_set_more_text:n}
+%\begin{macro}[aux]{\msg_generic_set_code:n}
+% Creating a message is quite simple. There must be a short text part,
+% while the other parts may not exist. To avoid filling up the hash
+% table with empty functions,only non-empty arguments are stored.
+% The various auxiliary functions are used to allow spaces in the
+% text arguments.
+% \begin{macrocode}
+\cs_new_nopar:Npn \msg_generic_set:nnnn #1 {
+ \msg_generic_set_clist:n {#1}
+ \char_make_space:N \ %
+ \msg_generic_set_code:nnnn{#1}%
+}
+\cs_new_nopar:Npn \msg_generic_set:nnn #1 {
+ \msg_generic_set_clist:n {#1}
+ \char_make_space:N \ %
+ \msg_generic_set_more_text:nnn{#1}%
+}
+\cs_new_nopar:Npn \msg_generic_set:nn #1 {
+ \msg_generic_set_clist:n {#1}
+ \char_make_space:N \ %
+ \msg_generic_set_text:nn{#1}%
+}
+\cs_new_nopar:Npn \msg_generic_set_clist:n #1 {
+ \clist_if_in:NnF \l_msg_names_clist { // #1 / } {
+ \clist_put_right:Nn \l_msg_names_clist { // #1 / }
+ }
+}
+\cs_new:Nn \msg_generic_set_text:nn {
+ \cs_set:cn { \c_msg_text_prefix_tl #1 :nn } {#2}
+ \char_make_ignore:N \
+}
+\cs_new:Nn \msg_generic_set_more_text:nnn {
+ \cs_set:cn { \c_msg_text_prefix_tl #1 :nn } {#2}
+ \tl_if_empty:nTF {#3} {
+ \cs_set_eq:cN { \c_msg_more_text_prefix_tl #1 } \c_undefined
+ }{
+ \cs_set:cn { \c_msg_more_text_prefix_tl #1 :nn } {#3}
+ }
+ \char_make_ignore:N \
+}
+\cs_new:Npn \msg_generic_set_code:nnnn #1#2#3 {
+ \cs_set:cn { \c_msg_text_prefix_tl #1 :nn } {#2}
+ \tl_if_empty:nTF {#3} {
+ \cs_set_eq:cN { \c_msg_more_text_prefix_tl #1 } \c_undefined
+ }{
+ \cs_set:cn { \c_msg_more_text_prefix_tl #1 :nn } {#3}
+ }
+ \char_make_ignore:N \
+ \msg_generic_set_code:nn {#1}
+}
+\cs_new:Nn \msg_generic_set_code:nn {
+ \tl_if_empty:nTF {#2} {
+ \cs_set_eq:cN { \c_msg_code_prefix_tl #1 : } \c_undefined
+ }{
+ \cs_set:cn { \c_msg_code_prefix_tl #1 : } {#2}
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_direct_interrupt:xxxxn}
+%\begin{macro}[aux]{\msg_direct_interrupt:n}
+% 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 spaces. To achieve this,
+% spaces have to be letters: hence no indentation. The odd
+% \cs{c_msg_hide_tl} actually does the hiding: it is the large run of
+% spaces 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}
+\group_begin:
+ \char_set_lccode:nn {`\&} {`\ } % {
+ \char_set_lccode:w `\} = `\ \scan_stop:
+ \char_make_active:N \&
+ \char_make_letter:N\ %
+\tl_to_lowercase:n{%
+\group_end:%
+\cs_new_protected:Nn\msg_direct_interrupt:xxxxn{%
+\group_begin:%
+\cs_set_eq:NN\\\msg_newline:%
+\cs_set_eq:NN\ \msg_space:%
+\msg_direct_interrupt_aux:n{#4}%
+\cs_set_nopar:Npn\\{\msg_newline:#3}%
+\tex_errhelp:D\l_msg_tmp_tl%
+\cs_set:Npn&{%
+\tex_errmessage:D{%
+#1\msg_newline:%
+#2\msg_two_newlines:%
+\c_msg_help_text_tl%
+\c_msg_hide_tl %
+}%
+}%
+&%
+\group_end:%
+#5%
+}%
+}%
+\cs_new:Nn \msg_direct_interrupt_aux:n {
+ \tl_if_empty:nTF {#1} {
+ \tl_set:Nx \l_msg_tmp_tl { { \c_msg_no_info_text_tl } }
+ }{
+ \tl_set:Nx \l_msg_tmp_tl { {#1 } }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_direct_log:xx}
+%\begin{macro}{\msg_direct_term:xx}
+% Printing to the log or terminal without a stop is rather easier.
+% \begin{macrocode}
+\cs_new_protected:Nn \msg_direct_log:xx {
+ \group_begin:
+ \cs_set:Npn \\ { \msg_newline: #2 }
+ \cs_set_eq:NN \ \msg_space:
+ \iow_log:x { #1 \msg_newline: }
+ \group_end:
+}
+\cs_new_protected:Nn \msg_direct_term:xx {
+ \group_begin:
+ \cs_set:Npn \\ { \msg_newline: #2 }
+ \cs_set_eq:NN \ \msg_space:
+ \iow_term:x { #1 \msg_newline: }
+ \group_end:
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{General functions}
+%
+% The main functions for messaging are built around the separation of
+% module from the message name. These have short names as they will be
+% widely used.
+%
+%\begin{macro}{\msg_new:nnnnn}
+%\begin{macro}{\msg_new:nnnn}
+%\begin{macro}{\msg_new:nnn}
+%\begin{macro}{\msg_set:nnnnn}
+%\begin{macro}{\msg_set:nnnn}
+%\begin{macro}{\msg_set:nnn}
+% For making messages.
+% \begin{macrocode}
+\cs_new_nopar:Npn \msg_new:nnnnn #1#2 {
+ \msg_generic_new:nnnn { #1 / #2 }
+}
+\cs_new_nopar:Npn \msg_new:nnnn #1#2 {
+ \msg_generic_new:nnn { #1 / #2 }
+}
+\cs_new_nopar:Npn \msg_new:nnn #1#2 {
+ \msg_generic_new:nn { #1 / #2 }
+}
+\cs_new_nopar:Npn \msg_set:nnnnn #1#2 {
+ \msg_generic_set:nnnn { #1 / #2 }
+}
+\cs_new_nopar:Npn \msg_set:nnnn #1#2 {
+ \msg_generic_set:nnn { #1 / #2 }
+}
+\cs_new_nopar:Npn \msg_set:nnn #1#2 {
+ \msg_generic_set:nn { #1 / #2 }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_class_new:nn}
+%\begin{macro}{\msg_class_set:nn}
+% Creating a new class produces three new functions, with varying
+% numbers of arguments. The \cs{msg_class_loop:n} function is set up
+% so that redirection will work as desired.
+% \begin{macrocode}
+\cs_new_nopar:Npn \msg_class_new:nn #1 {
+ \exp_args:Nc \chk_if_free_cs:N { msg_ #1 :nnxx }
+ \prop_new:c { l_msg_redirect_ #1 _prop }
+ \msg_class_set:nn {#1}
+}
+\cs_new_nopar:Nn \msg_class_set:nn {
+ \prop_clear:c { l_msg_redirect_ #1 _prop }
+ \cs_set_protected:cn { msg_ #1 :nnxx } {
+ \msg_use:nnnnxx {#1} {#2} {##1} {##2} {##3} {##4}
+ }
+ \cs_set_protected:cn { msg_ #1 :nnx } {
+ \use:c { msg_ #1 :nnxx } {##1} {##2} {##3} { }
+ }
+ \cs_set_protected:cn { msg_ #1 :nn } {
+ \use:c { msg_ #1 :nnxx } {##1} {##2} { } { }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}[aux]{\msg_use:nnnnxx}
+% 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:Nn \msg_use:nnnnxx {
+ \cs_set:Nn \msg_use_code: {
+ \clist_clear:N \l_msg_redirect_classes_clist
+ #2
+ }
+ \cs_set:Nn \msg_use_loop:n {
+ \clist_if_in:NnTF \l_msg_redirect_classes_clist {#1} {
+ \msg_kernel_error:n { message~loop }
+ }{
+ \clist_put_right:Nn \l_msg_redirect_classes_clist {#1}
+ \cs_if_exist:cTF { msg_ ##1 :nnxx } {
+ \use:c { msg_ ##1 :nnxx } {#3} {#4} {#5} {#6}
+ }{
+ \msg_kernel_error:nx { message~class~unknown } { ##1 }
+ }
+ }
+ }
+ \cs_if_exist:cTF { \c_msg_text_prefix_tl #3 / #4 :nn } {
+ \msg_use_aux:nnn {#1} {#3} {#4}
+ }{
+ \msg_kernel_error:nxx { message~unknown } { #3 } { #4 }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}[aux]{\msg_use_code:}
+%\begin{macro}[aux]{\msg_use_loop:}
+% Blank definitions are initially created for these functions.
+% \begin{macrocode}
+\cs_new_nopar:Nn \msg_use_code: { }
+\cs_new_nopar:Nn \msg_use_loop:n { }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}[aux]{\msg_use_aux:nnn}
+% The first auxiliary macro looks for a match by name: the most
+% restrictive check.
+% \begin{macrocode}
+\cs_new_nopar:Nn \msg_use_aux:nnn {
+ \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}
+%\end{macro}
+%\begin{macro}[aux]{\msg_use_aux:nn}
+% The second function checks for general matches by module or for
+% all modules.
+% \begin{macrocode}
+\cs_new_nopar:Nn \msg_use_aux:nn {
+ \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}
+%\end{macro}
+%\begin{macro}[aux]{\msg_use_loop_check:nn}
+% When checking whether to loop, the same code is needed in a few
+% places.
+% \begin{macrocode}
+\cs_new:Nn \msg_use_loop_check:nn {
+ \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:n { \l_msg_class_tl }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\msg_fatal:nnxx}
+%\begin{macro}{\msg_fatal:nnx}
+%\begin{macro}{\msg_fatal:nn}
+% For fatal errors, after the error message \TeX\ bails out.
+% \begin{macrocode}
+\msg_class_new:nn { fatal } {
+ \msg_direct_interrupt:xxxxn
+ { \c_msg_fatal_tl \msg_two_newlines: }
+ {
+ ( \c_msg_fatal_tl ) \msg_space:
+ \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4}
+ }
+ { ( \c_msg_fatal_tl ) \msg_space: }
+ { \c_msg_fatal_text_tl }
+ { \tex_end:D }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_error:nnxx}
+%\begin{macro}{\msg_error:nnx}
+%\begin{macro}{\msg_error:nn}
+% For an error, the interrupt routine is called, then any recovery code
+% is tried.
+% \begin{macrocode}
+\msg_class_new:nn { error } {
+ \msg_direct_interrupt:xxxxn
+ { #1~\c_msg_error_tl \msg_newline: }
+ {
+ ( #1 ) \msg_space:
+ \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4}
+ }
+ { ( #1 ) \msg_space: }
+ {
+ \cs_if_exist:cTF { \c_msg_more_text_prefix_tl #1 / #2 :nn } {
+ \use:c { \c_msg_more_text_prefix_tl #1 / #2 :nn } {#3} {#4}
+ }{
+ \c_msg_no_info_text_tl
+ }
+ }
+ {
+ \cs_if_exist:cT { \c_msg_code_prefix_tl #1 /#2 :nn } {
+ \use:c { \c_msg_code_prefix_tl #1 / #2 :nn} {#3} {#4}
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_warning:nnxx}
+%\begin{macro}{\msg_warning:nnx}
+%\begin{macro}{\msg_warning:nn}
+% Warnings are printed to the terminal.
+% \begin{macrocode}
+\msg_class_new:nn { warning } {
+ \msg_direct_term:xx {
+ \msg_space: #1~\c_msg_warning_tl :~
+ \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4}
+ }
+ { ( #1 ) \msg_two_spaces: }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_info:nnxx}
+%\begin{macro}{\msg_info:nnx}
+%\begin{macro}{\msg_info:nn}
+% Information only goes into the log.
+% \begin{macrocode}
+\msg_class_new:nn { info } {
+ \msg_direct_log:xx {
+ \msg_space: #1~\c_msg_info_tl :~
+ \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4}
+ }
+ { ( #1 ) \msg_two_spaces: }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_log:nnxx}
+%\begin{macro}{\msg_log:nnx}
+%\begin{macro}{\msg_log:nn}
+% ``Log'' data is very similar to information, but with no extras
+% added.
+% \begin{macrocode}
+\msg_class_new:nn { log } {
+ \msg_direct_log:xx {
+ \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4}
+ }
+ { }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_trace:nnxx}
+%\begin{macro}{\msg_trace:nnx}
+%\begin{macro}{\msg_trace:nn}
+% Trace data is the same as log data, more or less
+% \begin{macrocode}
+\msg_class_new:nn { trace } {
+ \msg_direct_log:xx {
+ \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4}
+ }
+ { }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_none:nnxx}
+%\begin{macro}{\msg_none:nnx}
+%\begin{macro}{\msg_none:nn}
+% The \texttt{none} message type is needed so that input can be gobbled.
+% \begin{macrocode}
+\msg_class_new:nn { none } { }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Redirection functions}
+%
+%\begin{macro}{\msg_redirect_class:nn}
+% Converts class one into class two.
+% \begin{macrocode}
+\cs_new_nopar:Nn \msg_redirect_class:nn {
+ \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_nopar:Nn \msg_redirect_module:nnn {
+ \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_nopar:Nn \msg_redirect_name:nnn {
+ \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_new:nn}
+%\begin{macro}{\msg_kernel_set:nnnn}
+%\begin{macro}{\msg_kernel_set:nnn}
+%\begin{macro}{\msg_kernel_set:nn}
+% 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_nopar:Npn \msg_kernel_new:nnnn #1 {
+ \msg_new:nnnnn { LaTeX } {#1}
+}
+\cs_new_nopar:Npn \msg_kernel_new:nnn #1 {
+ \msg_new:nnnn { LaTeX } {#1}
+}
+\cs_new_nopar:Npn \msg_kernel_new:nn #1 {
+ \msg_new:nnn { LaTeX } {#1}
+}
+\cs_new_nopar:Npn \msg_kernel_set:nnnn #1 {
+ \msg_set:nnnnn { LaTeX } {#1}
+}
+\cs_new_nopar:Npn \msg_kernel_set:nnn #1 {
+ \msg_set:nnnn { LaTeX } {#1}
+}
+\cs_new_nopar:Npn \msg_kernel_set:nn #1 {
+ \msg_set:nnn { LaTeX } {#1}
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}[aux]{\msg_kernel_classes_new:n}
+% Quickly make the fewer-arguments versions.
+% \begin{macrocode}
+\cs_new_nopar:Nn \msg_kernel_classes_new:n {
+ \cs_new_protected:cn { msg_kernel_ #1 :nx } {
+ \use:c { msg_kernel_ #1 :nxx } {##1} {##2} { }
+ }
+ \cs_new_protected:cn { msg_kernel_ #1 :n } {
+ \use:c { msg_kernel_ #1 :nxx } {##1} { } { }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\msg_kernel_fatal:nxx}
+%\begin{macro}{\msg_kernel_fatal:nx}
+%\begin{macro}{\msg_kernel_fatal:n}
+% Fatal kernel errors cannot be re-defined.
+% \begin{macrocode}
+\cs_new_protected:Nn \msg_kernel_fatal:nxx {
+ \msg_direct_interrupt:xxxxn
+ { \c_msg_fatal_tl \msg_two_newlines: }
+ {
+ ( LaTeX ) \msg_space:
+ \use:c { \c_msg_text_prefix_tl LaTeX / #1 :nn } {#2} {#3}
+ }
+ { ( LaTeX ) \msg_space: }
+ { \c_msg_fatal_text_tl }
+ { \tex_end:D }
+}
+\msg_kernel_classes_new:n { fatal }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_kernel_error:nxx}
+%\begin{macro}{\msg_kernel_error:nx}
+%\begin{macro}{\msg_kernel_error:n}
+% Neither can kernel errors.
+% \begin{macrocode}
+\cs_new_protected:Nn \msg_kernel_error:nxx {
+ \msg_direct_interrupt:xxxxn
+ { LaTeX~\c_msg_error_tl \msg_newline: }
+ {
+ ( LaTeX ) \msg_space:
+ \use:c { \c_msg_text_prefix_tl LaTeX / #1 :nn } {#2} {#3}
+ }
+ { ( LaTeX ) \msg_space: }
+ {
+ \cs_if_exist:cTF { \c_msg_more_text_prefix_tl LaTeX / #1 :nn } {
+ \use:c { \c_msg_more_text_prefix_tl LaTeX / #1 :nn } {#2} {#3}
+ }{
+ \c_msg_no_info_text_tl
+ }
+ }
+ {
+ \cs_if_exist:cT { \c_msg_code_prefix_tl LaTeX /#1 :nn } {
+ \use:c { \c_msg_code_prefix_tl LaTeX / #1 :nn} {#2} {#3}
+ }
+ }
+}
+\msg_kernel_classes_new:n { error }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\msg_kernel_warning:nxx}
+%\begin{macro}{\msg_kernel_warning:nx}
+%\begin{macro}{\msg_kernel_warning:n}
+%\begin{macro}{\msg_kernel_info:nxx}
+%\begin{macro}{\msg_kernel_info:nx}
+%\begin{macro}{\msg_kernel_info:n}
+% Life is much more simple for warnings and information messages, as
+% these are just short-cuts to the standard classes.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \msg_kernel_warning:nxx {
+ \msg_warning:nnxx { LaTeX }
+}
+\msg_kernel_classes_new:n { warning }
+\cs_new_protected_nopar:Npn \msg_kernel_info:nxx {
+ \msg_info:nnxx { LaTeX }
+}
+\msg_kernel_classes_new:n { info }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+% Some very basic error messages.
+% \begin{macrocode}
+\msg_kernel_new:nnn
+ { coding~bug }
+ {This is a LaTeX bug: check coding!\\#1}
+ {#2}
+\msg_kernel_new:nnn
+ { message~unknown }
+ {Unknown message `#2' for module `#1'.}
+ {LaTeX was asked to display a message by the `#1' module.\\
+ The message was supposed to be called `#2', but I can't\\
+ find a message with that name.
+ \c_msg_return_text_tl}
+\msg_kernel_new:nnn
+ { message~class~unknown }
+ {Unknown message class `#1'.}
+ {You have asked for a message to be redirected to class `#1'\\
+ but this class is unknown.
+ \c_msg_return_text_tl}
+\msg_kernel_new:nnn
+ { message~loop }
+ {Message redirection loop.}
+ {You have asked for a message to be redirected,\\
+ but the redirection instructions form a loop:\\
+ you've lost the message.
+ \c_msg_return_text_tl}
+% \end{macrocode}
+%
+%\begin{macro}{\msg_kernel_bug:x}
+% The \LaTeX\ coding bug error gets re-visited here.
+% \begin{macrocode}
+\cs_set_protected:Nn \msg_kernel_bug:x {
+ \msg_direct_interrupt:xxxxn
+ { \c_msg_kernel_bug_text_tl }
+ { !~#1 }
+ { ! }
+ { \c_msg_kernel_bug_more_text_tl }
+ { }
+}
+% \end{macrocode}
+%\end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex