% \iffalse
%% File: l3messages.dtx Copyright (C) 1990-2006 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/cgi-bin/cvsweb.cgi/
%%
%% 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.
%%
%% -----------------------------------------------------------------------
%
%<package>\RequirePackage{l3names}
%<package>\RequirePackage{l3basics}
%<package>\RequirePackage{l3tlp}
%<package>\RequirePackage{l3expan}
%<package>\RequirePackage{l3num}
%<package>\RequirePackage{l3io}
%<package>\RequirePackage{l3int}
%<package>\RequirePackage{l3toks}
%<*dtx>
%\fi
\def\GetIdInfo$Id: #1.dtx #2 #3-#4-#5 #6 #7$#8{%
  \def\fileversion{#2}%
  \def\filedate{#3/#4/#5}%
  \ProvidesFile{#1.dtx}[#3/#4/#5 v#2 #8]%
}
%\iffalse
%</dtx>
%\fi
\GetIdInfo$Id: l3messages.dtx 573 2006-08-21 20:59:37Z morten $
          {L3 Experimental LaTeX Messages module}
%
% \iffalse
%<*driver>
\documentclass{l3doc}

\begin{document}
\DocInput{l3messages.dtx}
\end{document}
%</driver>
% \fi
%
%
% \section{Communicating with the user}
%
%    Sometimes it is necesary to pass information back to the user
%    about what is going on. The information can be just that,
%    information, or it can be a warning that something might not
%    happen to his expectation. It could also be that something has
%    gone awry and that processing can't reliably continue without
%    some help from the user. In such a case an error is signalled.
%    When things are really bad, processing may have to stop as there
%    is no way to enter additional commands that put things right
%    again. In such a case we have a fatal error and the \LaTeX\ run
%    will be aborted.
%
% \subsection{Displaying the information}
%
%    First of all we need a couple of fairly low level functions that
%    deal with the job of passing the information to the user.
%
%    Real information is usually only written to the log file, while
%    warnings are displayed on the screen as well.
%  \begin{function}{%
%                     \err_info:nn |
%                     \err_warn:nn
%                     }
%    \begin{syntax}
%      "\err_info:nn" "{" <message> "}" "{"<continuation>"}"
%    \end{syntax}
%    The <message> will be written to the log file. When it contains
%    the command "\err_newline:" a line break will occur and the new
%    line will start with the <continuation>. The function
%    "\err_warn:nn" writes the message to the terminal as well.
%  \end{function}
%    When an erroneous situation is encountered, a message is
%    displayed and the user is given the opportunity to enter some
%    additional code in an attempt to put things right. He may first
%    ask for some help, in which case some extra text will be
%    displayed to him.
%  \begin{function}{\err_interrupt:NNw}
%    \begin{syntax}
%      "\err_interrupt:NNw" <err id> <label> <more args>
%    \end{syntax}
%    This function signals a user error by searching the error file
%    denoted by <err id> for an error message associated with <label>,
%    i.e., specified by a corresponding "\err_interrupt_new:NNNnnn"
%    command. Depending on the number of arguments specified as
%    <argno> when the error message was defined, further arguments are
%    read. Then the error message is displayed as explained in
%    "\err_interrupt_new:NNNnnn".
%  \end{function}
%
%    Finally, when something really serious occurs, \LaTeX\ will tell
%    the user about it and abort the run.
%  \begin{function}{\err_fatal:nn}
%    \begin{syntax}
%      "\err_fatal:nn" "{" <message> "}" "{"<continuation>"}"
%    \end{syntax}
%    Just displays the <message> and then aborts the \LaTeX\ run.
%  \end{function}
%
%  \begin{function}{\err_newline:}
%    \begin{syntax}
%      "\err_newline:"
%    \end{syntax}
%    Is used to break an informational, warning or error message up
%    into multiple lines. May be defined in such a way that the new
%    line starts with a standard <continuation>.
%  \end{function}
%
% \subsection{Storing the information}
%
%    The informational and warning messages are usually short and can
%    be stored as part of a macro; but error messages need to be more
%    verbose. Therefor error messages are stored in external files
%    which are read and searched for the correct error message at the
%    time of the error. In this way it is possible to write extensive
%    help texts without cluttering \TeX{}'s main memory. 
%
% \subsubsection{Dealing with the error file}
%
%  \begin{function}{\err_file_new:Nn}
%    \begin{syntax}
%      "\err_file_new:Nn" <err id> "{"<err file name>"}"
%    \end{syntax}
%    Opens a new error file to write errors to. <err id> is a unique
%    identifier for the external <err file name>. By convention <err
%    id> is  declared as a constant (i.e., starts with "\c_") und ends
%    with "_tlp". If this command is issued while some other error
%    file is open we get an internal error message.
%  \end{function}
%
%  \begin{function}{\err_file_close:N}
%    \begin{syntax}
%      "\err_file_close:N" <err id>
%    \end{syntax}
%    Closes the currently open error file and checks that it matches
%    <err id>, i.e., that everything is alright in the code.
%  \end{function}
%
% \subsubsection{Declaring an error message in the error file}
%  \begin{function}{\err_interrupt_new:NNNnnn}
%    \begin{syntax}
%      "\err_interrupt_new:NNNnnn"  <err id> <label> <argno>
%                               "{" <short msg> "}"
%                               "{" <long msg>  "}"
%                               "{" <recovery code> "}"
%    \end{syntax}
%    This function declares an new error message which can be
%    addressed via "\err_interrupt:NNw". The pair (<err id>, <label>)
%    has to be unique where <label> can be some otherwise arbitrary
%    token (usually the function name in which the error routine is
%    called. Actually, the pair (<err id>, expansion of <label>) has
%    to be unique since for reasons of speed, tests are carried out
%    using "\if_meaning:NN".
%
%    <argno> specifies the number of extra arguments that will be
%    supplied to the error routine when "\err_interrupt:NNw" is
%    called. These arguments can be used within <short msg>, <long
%    msg>, and/or <recovery code> to provide further information to
%    the user. They are denoted with "#1", "#2", etc.\ within these
%    arguments. 
%
%    The <short msg> is displayed directly on the terminal if the
%    error occurs, <long msg> is displayed when the user types "h" in
%    response to the error prompt of \TeX{}, and <recovery code> is
%    executed afterwards.  This means that <recovery code> is inserted
%    after any deletions or insertions given by the user. All three
%    arguments are expanded while they are written to the error file,
%    therefore one has to prevent expansion of tokens with
%    "\token_to_string:N" that should be expanded when the error is
%    triggered.
%  \end{function}
%
% \subsection{Internal functions}
%
%  \begin{function}{\err_display_aux:w}
%    This function is constructed on the fly while reading the error file.
%    It grabs following arguments from the code (if any) and then displays
%    the error message and inserts the <recovery code>.
%  \end{function}
%
%  \begin{function}{\err_interrupt_new_aux:w}
%    Helper function used to write the error message info onto the error
%    file.
%  \end{function}
%
%  \begin{function}{\err_msgline_aux:NNnnn}
%    \begin{syntax}
%   "\err_msgline_aux:NNnnn"  <argno> <label> "{"<short>"}"
%                             "{"<long msg>"}{"<recovery code>"}"
%   \end{syntax}
%    Function written in front of every error message on the error file. It
%    will be executed when the error file is read back in comparing <label>
%    to "\l_err_label_token". If they are the same, "\err_display_aux:w"
%    will be defined and the reading process will stop.
%  \end{function}
%
%  \begin{function}{\err_message:x}
%    \begin{syntax}
%      "\err_message:x" "{"<error message>"}"
%    \end{syntax}
%    Function that directly triggers \TeX{}'s error handler. It should
%    not be used directly. 
%    \begin{texnote}
%    This is the \LaTeX3 name for the \tn{errormessage} primitive.
%    \end{texnote}
%  \end{function}
%
% \subsection{Kernel specific functions}
%
%    For a number of the functions described above specific variants
%    are provided that are used in the kernel of \LaTeX3.
%
%    \begin{function}{%
%                     \err_kernel_info:n |
%                     \err_kernel_warn:n |
%                     \err_kernel_fatal:n
%                     }
%    \begin{syntax}
%      "\err_kernel_info:n" "{"<message>"}"
%    \end{syntax}
%    \end{function}
%  \begin{function}{%
%                  \err_kernel_interrupt:Nw |
%                  \err_kernel_interrupt_new:NNnnn |
%    }
%    Abbrivations for writing and accessing kernel error messages that
%    go to the error file "\c_kernel_err_tlp". 
%  \end{function}
%
%  \begin{function}{\err_latex_bug:x}
%    \begin{syntax}
%      "\err_latex_bug:x" "{"<error message>"}"
%    \end{syntax}
%    Creates an internal error message. This is intended to be used in
%    places that should not be reached in normal operation. Something is
%    wrong with the code. 
%  \end{function}
%
% \subsection{Variables and constants}
%
%    \begin{variable}{\iow_newline}
%    Identifier denoting the character that triggers a line break in
%    the output.
%    \end{variable}
%
%    \begin{variable}{\c_iow_err_stream}
%    Output stream used to access the error files during their
%    generation. 
%    \end{variable}
%
%    \begin{variable}{\c_kernel_err_tlp}
%    Identifier denoting the kernel error file. (Its contents is the
%    name of the external file.)
%    \end{variable}
%
%    \begin{variable}{\g_err_curr_fname}
%    Global variable containing the name of the currently open error
%    file. Empty when no such file is open for writing.
%    \end{variable}
%
%    \begin{variable}{\tex_errorcontextlines:D}
%    Variable determining the amount of macro expansion contents shown
%    to the user when an error is triggered. \LaTeX3 sets this to -1
%    since to the average user this contents is of no interest.
%    \begin{texnote}
%    This is the \LaTeX3 name for the \TeX3 primitive
%    \tn{errorcontextlines}.
%    \end{texnote}
%    \end{variable}
%
%    \begin{variable}{\g_err_help_toks}
%    Token register that holds the message that will be shown if the
%    user types "h" in response to an error message that was produced
%    by "\err_message:x". 
%    \begin{texnote}
%    This is the \LaTeX3 name for the \TeX\ primitive \tn{errhelp}.
%    \end{texnote}
%    \end{variable}
%
%    \begin{variable}{\l_err_label_token}
%    Variable holding the <label> to look up in an error file.
%    \end{variable}
%
% \StopEventually{}
%
% \subsection{The implementation}
%
%    \begin{macrocode}
%<*initex|package>
%    \end{macrocode}
%
% \subsubsection{Code to be moved to other modules}
%
% \begin{macro}{\g_file_curr_name_tlp}
%    This variable is used to store the name of the file currently
%    being processed. It should be part of the code that defines the
%    higher level I/O commands.
%    \begin{macrocode}
\tlp_new:Nn \g_file_curr_name_tlp {no~file}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\err_message:x}
%    The \LaTeX3 name for a \TeX\ primitive. This should perhaps move
%    to \texttt{l3names.dtx}.
%    \begin{macrocode}
\let_new:NN \err_message:x \tex_errmessage:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\text_put_sp:}
% \begin{macro}{\text_put_four_sp:}
%    We need these functions for certain error and warning messages
%    right away. They put one and four spaces into the message stream.
%    \begin{macrocode}
\def_new:Npn \text_put_sp: {~}
\def_new:Npn \text_put_four_sp: {\text_put_sp: \text_put_sp: 
                                 \text_put_sp: \text_put_sp: }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%  \begin{macro}{\cmd_arg_list_build}
%    This macro takes a digit as its argument and creates a string of
%    |#| characters and argument numbers, such as |##1##2##3|. This
%    list can then later be used in defining a new macro.
%    To do this it locally uses a count register and a token
%    register.
%
%    \begin{macrocode}
\def:Npn\cmd_arg_list_build#1{
%    \end{macrocode}
%    First we need to make sure that the token register we will be
%    using for temporary storage is empty.
%    \begin{macrocode}
  \toks_clear:N\l_tmpb_toks
%    \end{macrocode}
%    Then we can store the argument in a count register that will be
%    decremented untill it's value is zero. Beacuse of the use of the
%    result of this macro, the argument needs to be between 1 and 9;
%    this could be tested, but such a test is not (yet) added.
%    \begin{macrocode}
  \int_set:Nn \l_tmpa_int {#1}
  \int_while:nNnT \l_tmpa_int > \c_zero {
%    \end{macrocode}
%    In the loop we first add the value of our counter to the contents
%    of the token register;
%    \begin{macrocode}
    \toks_put_left:No \l_tmpb_toks {\the_internal:D\l_tmpa_int}
%    \end{macrocode}
%    and precede it with two hash marks.
%    \begin{macrocode}
    \toks_put_left:Nn \l_tmpb_toks {##}
%    \end{macrocode}
%    Now the count register is decremented and another iteration will
%    follow so long as zero isn't reached.
%    \begin{macrocode}
    \int_decr:N\l_tmpa_int
  }
%    \end{macrocode}
%    Finally the contents of the token register needs to be copied as
%    the expansion of a local variable.
%    \begin{macrocode}
  \def:Npx\l_cmd_arg_list{\the_internal:D\l_tmpb_toks}
}
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\cmd_declare:Nnn}
%    This macro is a first replacement for \LaTeXe's |\newcommand|. It
%    takes the name of a new macro as its first argument, the number
%    of arguments for the new macro is taken as the second argument.
%    \begin{macrocode}
\def:Npn\cmd_declare:Nnn#1[#2]{
  \cmd_arg_list_build{#2}
  \exp_args:NNO\def:Npn#1\l_cmd_arg_list
}
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\io_show_file_lineno:}
%    A function to add the number of the line and the name of the file
%    to a message as an indication of where the message was triggered. 
%    \begin{macrocode}
\def_new:Npn \io_show_file_lineno:{
  on~line~\the_internal:D\tex_inputlineno:D\text_put_sp:~of~
  file~\g_file_curr_name_tlp}
%    \end{macrocode}
%  \end{macro}
%
% \subsubsection{Variables and constants}
%
%  \begin{macro}{\g_err_help_toks}
%    A token register to store the help text for an error message in.
%    \begin{macrocode}
\let:NwN \g_err_help_toks \tex_errhelp:D
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\l_err_label_token}
%    This will hold the current error label.
%    \begin{macrocode}
\def_new:Npn \l_err_label_token {}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\tex_errorcontextlines:D}
%    Since we are producing our own error and help messages we can
%    turn off the nasty stack information coming from \TeX{}'s
%    stomach.
%    \begin{macrocode}
\int_set:Nn\tex_errorcontextlines:D\c_minus_one
%    \end{macrocode}
% \end{macro}
%
%  \subsubsection{Displaying the information}
%
%    Here we define the fairly low level commands needed to
%    communicate with the user.
%
%  \begin{macro}{\err_info:nn}
%  \begin{macro}{\err_warn:nn}
%    Write a message to the log file ("\err_info:nn") or to both the
%    log file and the terminal ("\err_warn:nn").
%    \begin{macrocode}
\def_new:Npn \err_info:nn #1#2{
%    \end{macrocode}
%    Make sure that the \emph{continuation} is part of "\err_newline:".
%    \begin{macrocode}
  \def:Npn\err_newline:{\iow_newline#2}
%    \end{macrocode}
%    Then write the message.
%    \begin{macrocode}
  \io_put_log:x {#1~\io_show_file_lineno:}}
\def_new:Npn \err_warn:nn #1#2{
  \def:Npn\err_newline:{\iow_newline#2}
  \io_put_term:x {#1~\io_show_file_lineno:}}
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%
%  \begin{macro}{\err_info_noline:nn}
%  \begin{macro}{\err_warn_noline:nn}
%    These variants of the above two functions don't add the
%    linenumber to the message.
%    \begin{macrocode}
\def_new:Npn \err_info_noline:nn #1#2{
  \def:Npn\err_newline:{\iow_newline#2}
  \io_put_log:x {#1}}
\def_new:Npn \err_warn_noline:nn #1#2{
  \def:Npn\err_newline:{\iow_newline#2}
  \io_put_term:x {#1}}
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%
% \begin{macro}{\err_interrupt:NNw}
%    |\err_interrupt:NNw| is the function that is called when some error
%    occurs in the code. It takes at least two arguments, the
%    \m{errfile} which is a token list that holds the name of the file
%    where the error message should be fetched from, and the label to
%    identify the error message in the error file. However, it may
%    have additional arguments that are picked up by the error handler
%    extracted from the error file. This is specified in the third
%    argument to |\err_interrupt_new:NNNnnn|.
%    \begin{macrocode}
\def_new:Npn \err_interrupt:NNw #1#2{\let:NwN \l_err_label_token #2
     \group_begin:
%    \end{macrocode}
%    For some reason we get some |\par|s into the file if we use the
%    current definition of |\iow_long_unxepanded:N| to write the messages.
%    This is probably a consequence of using token registers to
%    prohibit the expansion of code.
%    \begin{macrocode}
       \let:NwN \par\use_noop:
%    \end{macrocode}
%    We want to ensure that we are not in programmer's mode (no spaces)
%    but we want to switch on internal naming conventions.
%    \begin{macrocode}
       \CodeStop
       \NamesStart:
%    \end{macrocode}
%    We better clear all short references that are active, otherwise
%    we may get surprising results.
%    \begin{macrocode}
       %\clearshortrefmaps
       \tex_input:D #1~\err_display_aux:w}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\err_fatal:nn}
% \begin{macro}{\err_fatal_noline:nn}
%    Write a message to the log file and to the terminal.
%    \begin{macrocode}
\def_new:Npn \err_fatal:nn #1#2{
%    \end{macrocode}
%    Make sure that the \emph{continuation} is part of "\err_newline".
%    \begin{macrocode}
  \def:Npn\err_newline:{\iow_newline#2}
%    \end{macrocode}
%    Then write the message.
%    \begin{macrocode}
  \io_put_term:x {#1~\io_show_file_lineno:}
%    \end{macrocode}
%    Finally abort the \LaTeX{} run.
%    \begin{macrocode}
  \tex_end:D
  }
%    \end{macrocode}
%    A variant that doesn't include the line number where the error
%    occured.
%    \begin{macrocode}
\def_new:Npn \err_fatal_noline:nn #1#2{
  \def:Npn\err_newline:{\iow_newline#2}
  \io_put_term:x {#1}
  \tex_end:D
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\err_newline:}
%    |\err_newline:| is used to introduce a new line in an error
%    message. I would like to use |\\| but this would mean
%    redefinition which should be avoided to make the error message
%    the last action before control is given to the user (otherwise
%    something like |\group_end:| would interfere with
%    insertions/deletions by the user). "\err_newline:" will be
%    redefined by the various functions displaying messages to include
%    the correct \emph{continuation}.
%    \begin{macrocode}
\def_new:Npn \err_newline: {^^J}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Dealing with the error file}
%
% This section contains code that combines Michaels original thoughts
% on the the subject with Denys' further ideas.
%
% \begin{macro}{\c_iow_err_stream}
%    Error messages are logged using the output stream
%    |\c_iow_err_stream|.
%    \begin{macrocode}
\iow_new:N \c_iow_err_stream
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\g_err_curr_fname}
%    A nick name for the currently open error file. It is empty
%    if no error file is currently open.
%    \begin{macrocode}
\tlp_new:Nn \g_err_curr_fname{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\err_file_new:Nn}
%    This function defines a new error file. The first argument is a
%    token list which should hold the name of the error file, the second
%    argument is the name of the error file. The token list should be
%    a constant defined by this function.
%    \begin{macrocode}
\def_new:Npn \err_file_new:Nn #1#2{
   \tlp_if_empty:NF\g_err_curr_fname
      {\err_latex_bug:x{Unclosed~error~file~`\g_err_curr_fname'}}
   \iow_open:Nn \c_iow_err_stream {#2}
   \err_kernel_info:n{Errorfile~`#2'~opened~for~output}
   \tlp_gset:Nn \g_err_curr_fname{#2}
   \tlp_new:Nn #1{#2}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\err_file_close:N}
%    This function closes the current error file.
%    \begin{macrocode}
\def_new:Npn \err_file_close:N#1{
%    \end{macrocode}
%    Before we close the stream, we write out a final error handler
%    that catches mismatch within error message labels and their
%    calls. Actually this should be integrated into
%    |\err_file_new:Nn|, too.
%    \begin{macrocode}
  \tlp_if_eq:NNF#1\g_err_curr_fname
     {\err_latex_bug:x{You~closed~the~wrong~error~file~`#1'.~
         Open~is~`\g_err_curr_fname'.}}
  \iow_long_unexpanded:Nn \c_iow_err_stream {\err_latex_bug:x{Didn't~find~the~
        correct~error~message~to~show.\iow_newline
        Was~searching~for~a~function~
        with~the~following~meaning:\iow_newline
          \token_to_string:N\token_to_meaning:N
          \token_to_string:N\l_err_label_token}
%    \end{macrocode}
%    The |\group_end:| here matches the one from |\err_interrupt:NNw| that
%    is used to hide changes to |\par| etc.
%    \begin{macrocode}
      \group_end:}
  \iow_close:N \c_iow_err_stream
  \err_kernel_info:n{Errorfile~`\g_err_curr_fname'~closed}
  \tlp_gset_eq:NN\g_err_curr_fname\c_empty_tlp
}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Declaring an error message in the error file}
%
% \begin{macro}{\err_interrupt_new:NNNnnn}
%    This function declares a new error message.
%    |\err_interrupt_new:NNNnnn| \m{errfile} \m{errlabel} \m{argno}
%    \m{errmsg} \m{helpmsg} \m{code}. That error message is fetched
%    from the error file \m{errfile}. The label to search for is
%    \m{errlabel}, the error handler has \m{argno} number of arguments
%    (actually \m{argno} + 3 since the \m{errmsg}, \m{helpmsg} and
%    \m{code} are also arguments), and \m{errmsg} is the message to
%    display, \m{helpmsg} is the message that is displayed when the
%    user enters |h|, while \m{code} is extra code to perform when the
%    error occurs. \m{code} is perhaps not necessary, we will see.
%
%    We have to check that the label associated with the error message
%    is unique. This means that its replacement text (labels are
%    simply arbitrary functions) is different from the replacement
%    text of any other label in the same error set.
%    \begin{macrocode}
\def_new:Npn \err_interrupt_new:NNNnnn #1{
%    \end{macrocode}
%    Both \m{errmsg} and \m{code} might contain hashmarks denoting
%    arguments to the error handler.
%    \begin{macrocode}
  \group_begin: \tex_catcode:D`\#\c_other_char_code
%    \end{macrocode}
%    We also have to check that output goes to the correct error file.
%    \begin{macrocode}
  \if_meaning:NN#1\g_err_curr_fname
  \else:
      \err_latex_bug:x{Error~text~goes~to~wrong~err~file:~
          `\g_err_curr_fname'~is~open~but~you~requested~
          `#1'}
  \fi:
  \err_interrupt_new_aux:w}
\def_long_new:Npn \err_interrupt_new_aux:w #1#2#3#4#5{
  \iow_long_unexpanded:Nn \c_iow_err_stream
        {\err_msgline_aux:NNnnn #1#2{#3}{#4}{#5}\use_noop:}
  \group_end:}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\err_msgline_aux:NNnnn}
%    This function is executed when an error file is read back by
%    |\err_interrupt:NNw|.  It compares its first argument against
%    |\l_err_label_token| using |\if_meaning:NN| and if this fails the
%    function does nothing; otherwise it defines |\err_display_aux:w| in
%    a way that it will pick up the arguments (if any) from the code and
%    generates a suitable error message.
%    \begin{macrocode}
\def_new:Npn \err_msgline_aux:NNnnn #1#2#3#4#5{
  \if_meaning:NN#1\l_err_label_token
%    \end{macrocode}
%    At the moment we simply use the old \LaTeX{} error code and
%    |\renewcommand| to generate the error handler.  After displaying
%    the error message we insert error code this can be manipulated by
%    the user with the deletion/insertion facility of \TeX{}'s error
%    mechanism.
%
%    The |\group_end:| at the very beginning matches the
%    |\group_begin:| when the file starts.
%    \begin{macrocode}
        \cmd_declare:Nnn\err_display_aux:w [#2]{
           \group_end:
           \toks_gset:Nx\g_err_help_toks{#4}
           \io_put_term:x{LaTeX~error~\io_show_file_lineno:.\iow_newline
               \text_put_sp:\text_put_four_sp: \text_put_sp:
               See~LaTeX~manual~for~explanation.\iow_newline
               \text_put_sp:\text_put_four_sp: \text_put_sp:
               Type~\text_put_sp: H~<return>~\text_put_sp: for~
               immediate~help.}
           \err_message:x{#3}
           #5}
        \tex_endinput:D
   \fi:}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\err_display_aux:w}
%    We should make sure that this function is definable.
%    \begin{macrocode}
\def_new:Npn \err_display_aux:w {}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Kernel specific functions}
%
% \begin{macro}{\err_kernel_interrupt:Nw}
%    |\err_kernel_interrupt:Nw | is just the abbreviation to read from
%    the standard system error file.
%    \begin{macrocode}
\def_new:Npn \err_kernel_interrupt:Nw {\err_interrupt:NNw \c_kernel_err_tlp}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\err_kernel_interrupt_new:NNnnn}
%    To ease the coding in case of system messages that should all go
%    to one and the same error file (if!) we also have the following
%    function.
%    \begin{macrocode}
\def_new:Npn \err_kernel_interrupt_new:NNnnn {
        \err_interrupt_new:NNNnnn \c_kernel_err_tlp}
%    \end{macrocode}
% \end{macro}
%
%  \begin{macro}{\err_kernel_info:n}
%  \begin{macro}{\err_kernel_warn:n}
%  \begin{macro}{\err_kernel_fatal:n}
%  \begin{macro}{\err_kernel_info_noline:n}
%  \begin{macro}{\err_kernel_warn_noline:n}
%  \begin{macro}{\err_kernel_fatal_noline:n}
%    These variants are specific for the \LaTeX\ kernel.
%    \begin{macrocode}
\def_new:Npn \err_kernel_info:n #1 {
  \err_info:nn {LaTeX~Info:~#1}
               {\text_put_four_sp:\text_put_four_sp:\text_put_four_sp:}
  }
\def_new:Npn \err_kernel_warn:n #1 {
  \err_warn:nn {LaTeX~Warning:~#1}
               {\text_put_sp:\text_put_sp:\text_put_sp:
                \text_put_four_sp:\text_put_four_sp:\text_put_four_sp:}
  }
\def_new:Npn \err_kernel_fatal:n #1 {
  \err_fatal:nn {LaTeX~Fatal:~#1}
                {\text_put_sp:
                 \text_put_four_sp:\text_put_four_sp:\text_put_four_sp:}
  }
\def_new:Npn \err_kernel_info_noline:n #1 {
  \err_info_noline:nn {LaTeX~Info:~#1}
               {\text_put_four_sp:\text_put_four_sp:\text_put_four_sp:}
  }
\def_new:Npn \err_kernel_warn_noline:n #1 {
  \err_warn_noline:nn {LaTeX~Warning:~#1}
               {\text_put_sp:\text_put_sp:\text_put_sp:
                \text_put_four_sp:\text_put_four_sp:\text_put_four_sp:}
  }
\def_new:Npn \err_kernel_fatal_noline:n #1 {
  \err_fatal_noline:nn {LaTeX~Fatal:~#1}
                {\text_put_sp:
                 \text_put_four_sp:\text_put_four_sp:\text_put_four_sp:}
  }
%</initex|package>
%    \end{macrocode}
%    At a later stage variants may be provided for what in \LaTeXe{}
%    used to be called document classes and packages.
%  \end{macro}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%
% \begin{macro}{\c_kernel_err_tlp}
%    Most error messages will go to the system error file; it's name is
%    stored in |\c_kernel_err_tlp|.
%    \begin{macrocode}
%<initex>\err_file_new:Nn \c_kernel_err_tlp {ltxkernel.err}
%<package>\err_file_new:Nn \c_kernel_err_tlp {l3in2e.err}
%    \end{macrocode}
% \end{macro}
%
%    The code below is a temporary implementation of a few of
%    \LaTeX209 error messages with the new syntax. They are only
%    included in the package as the \LaTeX3 kernel will certainly have
%    it's own error message definitions that differ from \LaTeXe's way
%    of signalling errors. These primarily serve as an example on how
%    to use this concept of dealing with errors.
%
%    First we declare a couple of helper macros that contain texts
%    that are used frequently throughout \LaTeX.
%    \begin{macrocode}
%<*package>
\def:Npn\err_help_ignored: {
  Your~command~was~ignored.\iow_newline
  Type \text_put_sp: I~<command>~<return>
  \text_put_sp: to~replace~it~with~another~command,\iow_newline
  or~\text_put_sp: <return> \text_put_sp: to~continue~without~it.}

\def:Npn\err_help_textlost: {
  You've~lost~some~text.\text_put_sp: \err_help_return_or_X:}

\def:Npn\err_help_return_or_X: {
  Try~typing\text_put_sp: <return>
  \text_put_sp: to~proceed.\iow_newline
  If~that~doesn't~work,~type
  \text_put_sp: X~<return>\text_put_sp: to~quit.}

\def:Npn\err_help_trouble: {
  You're~ in~ trouble~ here.
  \text_put_sp:\err_help_return_or_X:}
%    \end{macrocode}
%
%    Below are the definitions of the complete messages
%    \begin{macrocode}

\err_kernel_interrupt_new:NNnnn\cs_free_p:N{1}
   {Command~name~`\tex_string:D#1'~already~used}
   {You~tried~to~define~a~command~which~already~has~
     a~meaning.\iow_newline
     If~you~really~want~to~redefine~it~try~
     \token_to_string:N\cmd_declare:Nnn\text_put_sp:
     next~time.\iow_newline
     For~this~run~I~will~ignore~your~definition.}
   {}

\err_kernel_interrupt_new:NNnnn\newline{0}
   {There's~no~line~here~to~end}
   {You~tried~to~end~a~line~at~a~place~where~I~thought~
     we~were~already~between~paragraphs.}
   {}

\err_kernel_interrupt_new:NNnnn\newcnt{0}
   {No~such~counter}
   {The~counter~name~mentioned~in~the~operation~is~not~
     known~to~me.\iow_newline
     Check~the~spelling.}
   {}

\err_kernel_interrupt_new:NNnnn\nodocument{0}
    {Missing~\token_to_string:N\begin{document}}
    {\err_help_trouble:}
    {}

\err_kernel_interrupt_new:NNnnn\badmath{0}
    {Bad~math~environment~delimiter}
    {\err_help_ignored:}
    {}

\err_kernel_interrupt_new:NNnnn\toodeep{0}
    {Too~deeply~nested}
    {\err_help_trouble:}
    {}

\err_kernel_interrupt_new:NNnnn\badpoptabs{0}
    {\token_to_string:N\pushtabs \text_put_sp: 
      and~\token_to_string:N\poptabs
      \text_put_sp: don't~match}
    {\err_help_trouble:}
    {}

\err_kernel_interrupt_new:NNnnn\badtab{0}
    {Undefined~tab~position}
    {\err_help_trouble:}
    {}

\err_kernel_interrupt_new:NNnnn\preamerr{}
    {\if_case:w #1~Illegal~character\or:
      Missing~@-exp\or: Missing~p-arg\fi:\text_put_sp:
      in~array~arg}
    {\err_help_trouble:}
    {}

\err_kernel_interrupt_new:NNnnn\badlinearg{}
    {Bad~\token_to_string:N\line
      \text_put_sp: or~\token_to_string:N\vector
      \text_put_sp: argument}
    {\err_help_textlost:}
    {}

\err_kernel_interrupt_new:NNnnn\parmoderr{0}
    {Not~in~outer~par~mode}
    {\err_help_textlost:}
    {}

\err_kernel_interrupt_new:NNnnn\fltovf{0}
    {Too~many~unprocessed~floats}
    {\err_help_textlost:}
    {}

\err_kernel_interrupt_new:NNnnn\badcrerr{0}
    {Bad~use~of~\token_to_string:N\\}
    {\err_help_return_or_X:}
    {}

\err_kernel_interrupt_new:NNnnn\noitemerr{0}
    {Something's~wrong--perhaps~a~missing~
      \token_to_string:N\item}
    {\err_help_return_or_X:}
    {}

\err_kernel_interrupt_new:NNnnn\notprerr{0}
    {Can~be~used~only~in~preamble}
    {\err_help_ignored:}
    {}

\err_file_close:N\c_kernel_err_tlp
%<package>
%    \end{macrocode}
%
%
%    Show token usage:
%    \begin{macrocode}
%<*showmemory>
\showMemUsage
%</showmemory>
%    \end{macrocode}
%
% \endinput
%
% $Log$
% Revision 1.9  2006/03/19 15:07:47  braams
% Moved some code to other modules, where it belongs;
% reverted \c_io_newline to \iow_newline (it'scontents might need to be
% modified sometine)
% Example messages are not part of the kernel, only for the package.
%
% Revision 1.8  2006/02/15 23:45:46  braams
% Rearranged the file;
% implemented \err_fatal:nn and \err_fatal_noline:nn
% Recode the remaining error definitions for testing purposes
%
% Revision 1.7  2006/01/15 09:48:54  braams
% Mostly textual changes
%
% Revision 1.6  2005/12/27 16:01:27  morten
% Changed RCS information retrieval plus a few minor changes
%
% Revision 1.5  2005/05/05 23:45:49  braams
% Worked on the documentation;
% added commands \err_info:nn, \err_warn:nn and kernel specific versions
% of these.
% Changed \iow_newline: into \c_io_newline; introduced \err_newline: to
% be used in messages with multiple lines to provide a continuation
% string.
% Renamed \style_names_start and \style_names_stop: into \NamesStart:
% and \NamesStop:.
%
% Revision 1.4  2005/05/03 23:34:52  braams
% Added code that performs the basic function of the old \renewcommand
% Added a couple of new functions that need to live in other modules
% Documentation still needs to be corrected
% The module now basically works
%
% Revision 1.3  2005/04/29 22:39:47  braams
% Another one
%
% Revision 1.2  2005/04/29 22:34:39  braams
% Small typo in the RCS tags
%
% Revision 1.1  2005/04/29 22:30:44  braams
% first version that can be loaded without producing errors.
% Just a translation from the old stuff, haven't looked at the docu yet