% \iffalse meta-comment
%
% Copyright (C) 2015 by Timothy Bourke <tim@tbrk.org>
%                    and Marc Pouzet <pouzet@ens.fr>
% -------------------------------------------------------
% 
% This file may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.2
% of this license or (at your option) any later version.
% The latest version of this license is in:
%
%    http://www.latex-project.org/lppl.txt
%
% and version 1.2 or later is part of all distributions of LaTeX version 
% 1999/12/01 or later.
%
% CTAN Topic: callback, listing
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{checklistings.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{checklistings}
%<package>   [2015/09/01 v1.0 compile code samples and insert the results]
%<package>\RequirePackage{keyval}
%<package>\RequirePackage{kvoptions}
%<package>\RequirePackage{fancyvrb}
%<package>\RequirePackage{color}
%<package>\RequirePackage{listings}
%<package>\makeatletter
%<package>\lst@RequireAspects{writefile}
%<package>\SetupKeyvalOptions{family=CHKL,prefix=CHKL@}
%<package>\makeatother
%
%<*driver>
\documentclass{ltxdoc}

\usepackage{checklistings}
\usepackage{url}
\usepackage{hypdoc}
\usepackage{showexpl}
\usepackage{array}
\usepackage{longtable}

\lstset{
    basicstyle=\small\ttfamily,
    numbers=none,
    keywordstyle=\color{blue}\bfseries,
    pos=l,
}

\checklistings{
  msgstyle={formatcom=\footnotesize},
  errstyle={formatcom=\footnotesize}}

\EnableCrossrefs         \CodelineIndex
\RecordChanges

\newcommand{\refsec}[1]{Section~\ref{sec:#1}}

\begin{document}
  \DocInput{checklistings.dtx}
  \PrintChanges
  \PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{444}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
%
% \changes{v1.0}{2015/09/01}{Initial version}
%
% \GetFileInfo{checklistings.sty}
%
% \DoNotIndex{\newcommand,\newenvironment}
% \DoNotIndex{\@file,\@ifundefined,\@tempboxa,\@undefined}
% \DoNotIndex{\arabic,\bgroup,\color,\dimexpr,\relax,\topsep,\vspace}
% \DoNotIndex{\CurrentOption,\DeclareBoolOption,\DeclareComplementaryOption}
% \DoNotIndex{\DeclareDefaultOption,\DeclareStringOption,\DeclareVoidOption}
% \DoNotIndex{\def,\define@key,\edef,\egroup,\else,\emph,\expandafter}
% \DoNotIndex{\fi,\global,\hbox,\ifnum,\InputIfFileExists,\langle,\let}
% \DoNotIndex{\newcounter,\newif,\PackageWarning,\ProcessKeyvalOptions}
% \DoNotIndex{\rangle,\setbox,\setkeys,\space,\stepcounter}
% \DoNotIndex{\value,\@currentlabel,\@firstoftwo,\AtEndDocument,\em}
% \DoNotIndex{\closeout,\csname,\endcsname,\DefineVerbatimEnvironment}
% \DoNotIndex{\jobname,\kvsetkeys,\label,\newwrite,\noexpand,\openout}
% \DoNotIndex{\partopsep,\setlength,\thepage,\write,\resetcounteronoverlays}
% \DoNotIndex{\@tempa,\fvset,\ifx,\inputlineno,\lstset,\the}
% \DoNotIndex{\DeclareRobustCommand,\empty,\ifdefined,\meta}
% \expandafter\DoNotIndex\expandafter{\string\$}
% \expandafter\DoNotIndex\expandafter{\string\#}
%
% \title{The \textsf{checklistings} package\thanks{This document
%   corresponds to \textsf{checklistings}~\fileversion, dated \filedate.}}
% \author{Timothy Bourke and Marc Pouzet}
%
% \maketitle

% \section{Introduction}
%
% User manuals and papers about programming languages usually contain many 
% code samples, often with accompanying compiler messages giving the types 
% of declarations or error messages explaining why certain declarations are 
% invalid.
% This package extends 
% |fancyvrb|\footnote{\url{http://www.ctan.org/pkg/fancyvrb}} and 
% |listings|\footnote{\url{http://www.ctan.org/pkg/listings}}, which are 
% ideal for displaying code, with a way to pass code samples through a 
% compiler and include the resulting messages in a \LaTeX{} document.
% The motivation is to check the code samples in a document for syntax and 
% typing errors and to facilitate the inclusion of inferred types and 
% compiler warnings or errors in a text.
% This package is intentionally very lightweight and unlike packages like 
% |python|,\footnote{\url{http://www.ctan.org/pkg/python}} it is not 
% intended for interacting with an interpretor or including the execution 
% traces of code.
% While it does not focus on a specific programming language, it is designed 
% to work well with ML-like languages.
%
% As an example, the text at left below is generated by the \LaTeX{} code at 
% right:
%
% \iffalse
%<*example>
% \fi
\begin{LTXexample}
Code samples are included
verbatim and the results of
compilation can be included
automatically:
\begin{chklisting}[withresult]
let inc x = x + 1
let y = inc 3
\end{chklisting}
\end{LTXexample}
% \iffalse
%</example>
% \fi
%
% A first pass through |latex| generates both a |.chkl| file,
% with parameters for the compiler, and an |.ml| file containing the source 
% code (i.e., the two lines in the example above).
% Running the |checklistings.sh| script processes these files to produce a 
% |.tex| file with the results of compilation.
% A second pass through |latex| updates the compiler message.
%
% \noindent
% It is possible to continue examples and to label them (to be continued at 
% some later point):
% \iffalse
%<*example>
% \fi
\begin{LTXexample}[pos=b]
These definitions follow on from the previous ones:
\begin{chklisting}[continue,withresult,label=early]
let z = y + inc y
\end{chklisting}
\end{LTXexample}
% \iffalse
%</example>
% \fi
%
% \bigskip\noindent
% Examples need not necessarily succeed:
% \iffalse
%<*example>
% \fi
\begin{LTXexample}[pos=b]
This code does not compile:
\begin{chklisting}[continue,fail,withresult,skipone]
let u = 3
let w = u + "four"
\end{chklisting}
\end{LTXexample}
% \iffalse
%</example>
% \fi
% Note that the line number in the error message is 1 even though the 
% |continue| option added a line to include the previous definitions and the 
% |skipone| option hid the |let u = 3| line.
% The |checklistings.sh| script performs this adjustment by looking for the 
% regular expression `|line  *[0-9][0-9]*|' and decrementing the number 
% appropriately.
% This approach is simple and effective but obviously not foolproof.
% Some manual tuning of the script may be required for correct results.
%
% \section{Use}\label{sec:use}
%
% Using the package involves three elements:
% \begin{enumerate}
%
% \item
% The declaration \verb|\usepackage{checklistings}|.\\
% \refsec{rvpkg} describes the options for configuring package behaviour.
%
% \item
% The environment \verb|chklisting|.\\
% This environment is used like any other verbatim environment.
% \refsec{rvenv} describes options that may be given to control its 
% behaviour.
%
% \item
% The script \verb|checklistings.sh|.\\
% Running this script passes the contents of each \verb|chklisting| 
% environment through a compiler or interpreter and copies the resulting 
% output into a file.
%
% \end{enumerate}
%
% Additionally, the file \verb|checklistings.hva| can be used to incorporate 
% the output of |checklistings| in HTML documents generated by 
% HeVeA.\footnote{\url{http://hevea.inria.fr}}
%
% \subsection{Package options}\label{sec:rvpkg}
%
% \DescribeMacro{\checklistings}
% Package options are either given as optional arguments to 
% \verb|\usepackage| or via one or more calls to \verb|\checklistings|.
% The advantage of the latter is that macros are not expanded (for a 
% detailed explanation see the documentation for 
% |kvoptions|,\footnote{\url{http://www.ctan.org/pkg/kvoptions}} Section 
% 4.1, \emph{Package kvoptions-patch}).
% Options are passed as a comma separated list of \meta{key}|=|\meta{value} 
% pairs and single \meta{key}s.
%
% There are three classes of options: options controlling the default 
% behaviour of \verb|chklisting|, options for configuring the 
% \verb|checklistings.sh| script, and options controlling the display of
% code and results.
%
% \subsubsection{Behavioural options}
%
% These options control the default behaviour of the \verb|chklisting| 
% environment.
%
% \begin{longtable}{@{}>{\ttfamily}lp{75mm}>{\ttfamily}l@{}}
% \parbox{15mm}{option} & description & \parbox{25mm}{default}\\\hline
% withresult
% & Automatically show compilation results.
% & false
% \\
% skipone
% & Do not display the first line of code (see the description under the 
% |chklisting| environment).
% &
% false
% \\
% skiptwo
% & Do not display the first two lines of code (see the description under 
% the |chklisting| environment).
% &
% false
% \\
% hideproblems
% & Globally disable the display of failure messages (within a red box) when 
% compilation fails or succeeds unexpectedly.
% &
% false
% \\
% \end{longtable}
%
% \subsubsection{Configuring compilation}\label{sec:compileconfig}
%
% These options are used for naming and placing the files generated by 
% \verb|chklisting| environments.
% They are passed to the \verb|checklistings.sh| script and thus control
% its behaviour.
%
% \makeatletter
% \begin{longtable}{@{}>{\ttfamily}lp{75mm}>{\ttfamily}l@{}}
% \parbox{15mm}{option} & description & \parbox{25mm}{default}\\\hline
% prefix
% & Prefix for naming source files.
%   It must not contain underscores (\verb|_|).
% & \CHKL@prefix
% \\
% ext
% & Extension of source files.
% & \CHKL@ext
% \\
% subdir
% & If defined, source files are created in the given subdirectory, which 
% must already exist.
% A final slash (\verb|/|) should not be given.
% The name must not contain underscores (\verb|_|).
% & \CHKL@subdir
% \\
% prompt
% & The prompt displayed by |\chklistingcmd|.
% & \CHKL@prompt
% \\
% compiler
% & Path of the compiler to execute.
% & \CHKL@compiler
% \\
% compilerflags
% & Flags passed to the compiler.
% These are not revealed by |\chklistingcmd|.
% & \CHKL@compilerflags
% \\
% lastflags
% & Flags passed to the compiler before the main source file, that is, the 
% last one given.
% & \CHKL@lastflags
% \\
% includecmd
% & The source language command for importing the definitions of another 
% file.
% & \CHKL@includecmd
% \\
% html
% & The path of a program that renders source code as html.
% This value can be useful when using HeVeA to produce web pages from 
% \LaTeX{} documents.
% In any case, it is optional.
% & \CHKL@html
% \end{longtable}
% \makeatother
%
% Each \verb|chklisting| environment is assigned a number $n$, from zero, 
% and its contents are written to the file:
% \meta{subdir}|/|\meta{prefix}\meta{n}|.|\meta{ext},
% where \meta{n} is zero-padded to four characters.
% For example, by default, the fourth environment is written to the file 
% \verb|chklisting0003.ml| in the current directory.
%
% Source lines are added for each dependency, and those files are compiled 
% using the \meta{compiler}, \meta{compilerflags}, and \meta{lastflags} 
% options.
% For example, if the fourth environment depends on the first and the 
% second, a line is added:
% \begin{center}
% \meta{includecmd} |Withopen0000| \meta{includecmd} |Withopen0001|,
% \end{center}
% where \verb|Withopen| is the prefix used for such augmented files, and the 
% compiler is invoked with:\\
% \begin{center}
% \begin{tabular}{ll}
% \meta{compiler}
%   & \meta{compilerflags}\ \ |Withopen0000|\ \ |Withopen0001| \\
%   & \meta{lastflags}\ \ |Withopen0003|
% \end{tabular}
% \end{center}
%
% \subsubsection{Controlling the display}
%
% This package exploits the display options given by the |fancyvrb| package.
%
% \begin{longtable}{@{}>{\ttfamily}lp{75mm}>{\ttfamily}l@{}}
% \parbox{15mm}{option} & description & \parbox{25mm}{default}\\\hline
% codestyle
% & |fancyvrb| options for code
% & \\
% msgstyle
% & |fancyvrb| options for compiler messages
% & formatcom=\string\em
% \\
% errstyle
% & |fancyvrb| options for error messages
% & formatcom=\string\em
% \\
% codelst
% & |listings| options for source code, passed with |\lstset|. When this 
% option is not empty, |fancyvrb=true| is included automatically.
% \\
% msglst
% & As for |codelst|, but applied to compiler messages.
% \\
% errlst
% & As for |codelst|, but applied to error messages.
% \\
% \end{longtable}
%
% Other options are passed directly through to the |fancyvrb| package and 
% applied to all |chklisting| code blocks (but not to messages or errors).
% For example, \verb|frame=single|.
% These options must typically be set using |\checklistings|, since they 
% will usually contain commands that should not be expanded immediately 
% (like |\em| or |\bf|).
%
% \subsection{The \texttt{chklisting} environment}\label{sec:rvenv}
%
% \DescribeEnv{chklisting}
% As an optional argument, this environment takes a comma separated list of 
% \meta{key}|=|\meta{value} and single \meta{key}s.
%
% \begin{longtable}{@{}>{\ttfamily}lp{100mm}}
% \parbox{15mm}{option} & description \\\hline
% fail
% & This code is expected to fail; an error is reported if it succeeds.
% \\
% continue
% & This code is continued from the previous |chklisting| environment; all 
% of the definitions available there are imported.
% \\
% label
% & Label this code for later inclusion.
% \\
% include
% & All of the definitions available after the environment with the given 
% label are imported.
% \\
% withresult
% & The result of compiling the code is displayed (see also 
% |\chklistingmsg| and |\chklistingerr|).
% This is normally either the types of declared values or the results of 
% evaluation.
% For environments marked |fail|, it will be an error message.
% \\
% withoutresult
% & The result of compiling code is not displayed automatically.
%   This is the default behaviour, but it can be overridden by the package 
%   options.
% \\
% hide
% & The code is not displayed, but it is still compiled, compiler messages 
% are still displayed (if |withresult| is active), and definitions are still 
% available for continuation (|continue|), labelling (|label|), and later 
% inclusion (|include|).
% \\
% skipone
% & Do not display the first line of the code.
%   This line is still sent to the compiler and may thus be used to open 
%   other modules, or to pass execution options (via comments).
% \\
% skiptwo
% & As pre the previous option, but two lines are skipped.
% \\
% skipnone
% & Do not skip any lines; this option overrides any package-level skip 
% setting.
% \\
% hideproblems
% & Do not display an error message within the document when compilation 
% fails or succeeds unexpectedly.
% \\
% showproblems
% & Display an error message within the document when compilation fails or 
% succeeds unexpectedly.
% This is the default behaviour unless the |hideproblems| package option was 
% set.
% \\
% \end{longtable}
%
% The results of compiling the code of a |chklisting| environment are made 
% available in the following macros until the next |chklisting| which will 
% redefine them.
% \begin{description}
%
% \item[\texttt{\string\chklistingcmd}]
% \DescribeMacro{\chklistingcmd}
% contains an idealised version of the command line used to compile the code 
% sample.
% It includes the |prompt|, the basename of |compiler|, and |lastflags|, but 
% not |compilerflags| or the list of included files.
% Furthermore, the |subdir| and serial number are removed from the filename 
% of the code sample, which becomes simply \meta{prefix}|.|\meta{ext}.
%
% \item[\texttt{\string\chklistingmsg\marg{label}}]
% \DescribeMacro{\chklistingmsg}: inserts the verbatim text emitted by the 
% compiler, provided compilation succeeded, for the |chklisting| 
% environment labelled \meta{label}.
% When \meta{label} is left empty, the message for the last environment is 
% inserted.
% It should not be used after environments marked |fail|.
%
% \item[\texttt{\string\chklistingerr\marg{label}}]
% \DescribeMacro{\chklistingerr}: inserts the verbatim text emitted by the 
% compiler, provided compilation failed, for the |chklisting| environment 
% labelled \meta{label}.
% When \meta{label} is left empty, the message for the last environment is 
% inserted.
% It should only be used after environments marked |fail|.
% \end{description}
%
% \subsection{The \texttt{checklistings.sh} script}\label{sec:rvsh}
%
% Processing a document that uses the |checklistings| package produces a 
% |.chkl| file containing compiler options and a list of source files 
% together with their interdependencies.
% The |checklistings.sh| script processes |.chkl| files by executing the 
% specified compiler against each listed source file 
% \meta{subdir}|/|\meta{prefix}\meta{n}|.|\meta{ext} and copying the 
% results---the command-line used, whether it succeeded or failed, the 
% messages on |stdout|, and the messages on |stderr|---into a corresponding 
% file, \meta{subdir}|/|\meta{prefix}\meta{n}|.tex|, for inclusion in the 
% original document.
%
% The \verb|checklistings.sh| script is written for the Bourne shell 
% (\verb|sh|).
% It takes a list of |.chkl| files as arguments (with or without the 
% exentions), but if none are given it processes all such files in the 
% current working directory.
%
% The compilation options specified within a \LaTeX{} source file, see
% \refsec{compileconfig}, can be manually overridden by processing a |.chkl| 
% file, before any others, containing a `|lock|' directive, for example:
% |lock compiler=/usr/local/bin/ocamlc|.
% This feature is useful when working with others to develop the compiler 
% being documented.
%
% \StopEventually{}
\makeatletter
%
% \section{Remarks}
%
% \subsection{Known limitations}
%
% The package and script have some known limitations.
% \begin{itemize}
% 
% \item
% Line numbers in error messages may not correspond correctly with the line 
% numbers of sample files, due to either the |skip*| options, or because of 
% lines added to import code.
%
% \item
% The system has been designed to work with ML-style compilers.
% It has not been tested with other compilers and interpreters.
% Please contact \url{tim@tbrk.org} if you would like to support other 
% systems.
% Patches are most welcome, but the intent is to keep this package 
% relatively simple rather than to try to do everything.
%
% \item
% Multiple languages in a single document are not supported.
%
% \item
% Care must be taken when using |checklistings| with the overlays of the 
% Beamer package.
% In particular, |chklisting| environment commands are to be avoided within 
% commands that completely omit material from slides, like |only|, |alt|, or 
% |temporal|, or with `closed' overlay specifications, like |2| or |1-3|.
% As these commands do not execute the material, the environment sequence 
% numbers do not increase monotonically, and the compilation results may not 
% be properly synchronized with the verbatim text.
% Commands that only hide material, or that introduce it successively, like 
% |uncover| or |visible|, or `open' overlay specifications, like |2-|, 
% should function as expected.
%
% \end{itemize}
%
% \section{Implementation}
%
% All internal macros have names of the form |\CHKL@|\meta{name}.
%
% \begin{macro}{\chklisting}
% Generate the sequence of source code identifiers used in per-environment 
% filenames and to manage dependencies.
% If |beamer| is being used, reset the counter on each overlay to avoid 
% generating multiple output files for the same program.
%    \begin{macrocode}
\newcounter{chklisting}
\ifdefined\resetcounteronoverlays
\resetcounteronoverlays{chklisting}
\fi
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifCHKL@fileexists}
% An internal boolean variable for remembering whether an input |.tex| file, 
% corresponding to the compilation of source code, was found.
%    \begin{macrocode}
\newif\ifCHKL@fileexists
%    \end{macrocode}
% \end{macro}
%
% \subsection{Package Options}
%
% The package options are processed using the |kvoptions| package.
%
% \begin{macro}{\CHKL@pkg@verbopts}
% This list accumulates package-level options for the |verbatim| 
% environments.
%    \begin{macrocode}
\def\CHKL@pkg@verbopts{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\CHKL@pkg@globalskip}
% Defines the number of lines to be skipped when displaying a code sample as 
% defined by the global options |skipone| and |skiptwo|.
%    \begin{macrocode}
\def\CHKL@pkg@globalskip{0}
%    \end{macrocode}
% \end{macro}
%
% \noindent
% Declare the package options and their default values:

%    \begin{macrocode}
\DeclareBoolOption{withresult}
\DeclareComplementaryOption{withoutresult}{withresult}
\DeclareBoolOption[true]{showproblems}
\DeclareComplementaryOption{hideproblems}{showproblems}
\DeclareVoidOption{skipone}
    {\edef\CHKL@pkg@globalskip{1}%
     \edef\CHKL@pkg@verbopts{\CHKL@pkg@verbopts,firstline=2}}
\DeclareVoidOption{skiptwo}
    {\edef\CHKL@pkg@globalskip{2}%
     \edef\CHKL@pkg@verbopts{\CHKL@pkg@verbopts,firstline=3}}
\DeclareDefaultOption
    {\edef\CHKL@pkg@verbopts{\CHKL@pkg@verbopts,\CurrentOption}}
\DeclareStringOption[]{codestyle}
\DeclareStringOption[formatcom=\em]{msgstyle}
\DeclareStringOption[formatcom=\em]{errstyle}
\DeclareStringOption{codelst}
\DeclareStringOption{msglst}
\DeclareStringOption{errlst}
\DeclareStringOption{emptyoption}
\DeclareStringOption[.]{subdir}
\DeclareStringOption[chklisting]{prefix}
\DeclareStringOption[.ml]{ext}
\DeclareStringOption[\#]{prompt}
\DeclareStringOption[ocamlc]{compiler}
\DeclareStringOption{compilerflags}
\DeclareStringOption[-i]{lastflags}
\DeclareStringOption[open]{includecmd}
\DeclareStringOption[]{html}
\ProcessKeyvalOptions*
%    \end{macrocode}
%
% \begin{macro}{\checklistings}
% This macro offers another way of setting package options with the 
% advantage that values are not expanded.
%    \begin{macrocode}
\def\checklistings{\kvsetkeys{CHKL}}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Logging Files to be Processed}
%
% Several definitions and commands are used to create and write to the 
% |.chkl| file.
%
% \begin{macro}{\CHKL@samplefile}
% The file generated when a \LaTeX{} document that uses the |checklistings| 
% package is processed.
%    \begin{macrocode}
\newwrite\CHKL@samplefile
\openout\CHKL@samplefile=\jobname.chkl
\AtEndDocument{\closeout\CHKL@samplefile}
%    \end{macrocode}
% \end{macro}
%
% Package options are logged to the file.
%    \begin{macrocode}
\write\CHKL@samplefile{subdir=\CHKL@subdir/}
\write\CHKL@samplefile{prefix=\CHKL@prefix}
\write\CHKL@samplefile{ext=\CHKL@ext}
\write\CHKL@samplefile{compiler=\CHKL@compiler}
\write\CHKL@samplefile{compilerflags=\CHKL@compilerflags}
\write\CHKL@samplefile{lastflags=\CHKL@lastflags}
\write\CHKL@samplefile{includecmd=\CHKL@includecmd}
\write\CHKL@samplefile{htmlfilter=\CHKL@html}
%    \end{macrocode}
%
% \begin{macro}{\CHKL@logsample}
% An entry is logged for each |chklisting| environment.
% It contains the sequence number for the example, followed by a colon, an 
% ordered list of other sample files to import, and the page and line 
% numbers (to include in error messages).
%    \begin{macrocode}
\DeclareRobustCommand{\CHKL@logsample}[2]{%
  \edef\CHKL@tolog{#1:#2 [page=\noexpand\thepage] [line=\the\inputlineno]}%
  \expandafter\write\expandafter\CHKL@samplefile\expandafter{\CHKL@tolog}%
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Insertion of Compilation Results}
%
% Several macros are defined for use by the |checklistings.sh| script (and
% any similar program).
% These macros are called from within the |.tex| file generated for each 
% |chklisting| environment.
%
% \begin{macro}{\ifchklisting}
% A successful compilation is signalled by |\chklistingtrue|, and a failed 
% compilation by |\chklistingfalse|.
%    \begin{macrocode}
\newif\ifchklisting
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\setchklistingcmd}
% The command used to compile a sample is recorded by |\setchklistingcmd| 
% which (re)defines the internal |\CHKL@prompt| value.
%    \begin{macrocode}
\DeclareRobustCommand{\setchklistingcmd}[1]{%
    \global\def\chklistingcmd{\emph{\CHKL@prompt{#1}}}}
%    \end{macrocode}
% \end{macro}

% \begin{environment}{ChkListingMsg}
% Normal compiler messages (written on |stdout|) should be communicated 
% between |\begin{ChkListingMsg}| and |\end{ChkListingMsg}|.
% This verbatim text is saved using the |SaveVerbatim| feature of 
% |fancyvrb|.
%    \begin{macrocode}
\def\ChkListingMsg{\FV@Environment{}{ChkListingMsg}}
\def\FVB@ChkListingMsg{\FVB@SaveVerbatim{ChkListingMsg}}
\let\FVE@ChkListingMsg\FVE@SaveVerbatim
\DefineVerbatimEnvironment{ChkListingMsg}{ChkListingMsg}{}
%    \end{macrocode}
% \end{environment}

% \begin{environment}{ChkListingErr}
% Compiler error messages (usually written on |stderr|) should be 
% communicated between |\begin{ChkListingErr}| and |\end{ChkListingErr}|.
% This verbatim text is saved using the |SaveVerbatim| feature of 
% |fancyvrb|.
%    \begin{macrocode}
\def\ChkListingErr{\FV@Environment{}{ChkListingErr}}
\def\FVB@ChkListingErr{\FVB@SaveVerbatim{ChkListingErr}}
\let\FVE@ChkListingErr\FVE@SaveVerbatim
\DefineVerbatimEnvironment{ChkListingErr}{ChkListingErr}{}
%    \end{macrocode}
% \end{environment}

% \begin{macro}{\chklistingfile}
% This is the filename used by |checklistings.sh| to refer to the file 
% containing sample code when |\setchklistingcmd| is called.
%    \begin{macrocode}
\DeclareRobustCommand{\chklistingfile}{\CHKL@prefix\CHKL@ext}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Main Environment}
%
% Several auxiliary definitions are needed to track per-environment 
% configuration options.
%
% \begin{macro}{\ifCHKL@shouldfail}
% This boolean variable records whether sample code is expected to fail.
%    \begin{macrocode}
\newif\ifCHKL@shouldfail
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifCHKL@showcode}
% This boolean variable records whether the compilation result should be 
% shown.
%    \begin{macrocode}
\newif\ifCHKL@showcode
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\CHKL@skip}
% Defines the number of lines to be skipped when displaying a code sample.
% It defaults to the value of |\CHKL@pkg@globalskip|, but may be altered by 
% the environment options |skipone| and |skiptwo|.
% This value is only used to generate the |skip=| field in the |.chkl| file.
% The actual skipping is done by the |firstline| option of |verbopts|.
% \begin{macrocode}
\def\CHKL@skip{0}
%    \end{macrocode}
% \end{macro}
%
% The |keyval| package\footnote{\url{http://www.ctan.org/pkg/keyval}} is 
% used to parse environment options.
% The following macros setup parameters used by the |chklisting| 
% environment.
%
% \begin{macro}{\CHKL@continue}
% \begin{macro}{\CHKL@precontinue}
% These two macros hold lists of source code identifiers: 
% |\CHKL@precontinue| tracks the dependencies of the previous |chklisting| 
% environment and |\CHKL@continue| tracks those of the current one.
% The |continue| option appends the previous dependencies onto the list of 
% current ones.
% The dependencies used at each labelled environment are remembered in 
% |\RBRB@deps|\meta{label}.
% The |include| option causes them to be added to the list of current 
% dependencies.
%
%    \begin{macrocode}
\edef\CHKL@precontinue{}
\define@key{CHKL@envkeys}{continue}[]{\edef\CHKL@continue{\CHKL@precontinue}}
\define@key{CHKL@envkeys}{include}{%
  \edef\CHKL@continue{\CHKL@continue\space\@ifundefined{CHKL@deps@#1}%
    {#1}{\csname CHKL@deps@#1\endcsname}}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
\define@key{CHKL@envkeys}{fail}[]{\CHKL@shouldfailtrue}
\define@key{CHKL@envkeys}{label}{\edef\CHKL@label{#1}}
\define@key{CHKL@envkeys}{skipnone}[]{%
  \edef\CHKL@skip{0}\edef\CHKL@verbopts{\CHKL@verbopts,firstline=1}}
\define@key{CHKL@envkeys}{skipone}[]{%
  \edef\CHKL@skip{1}\edef\CHKL@verbopts{\CHKL@verbopts,firstline=2}}
\define@key{CHKL@envkeys}{skiptwo}[]{%
  \edef\CHKL@skip{2}\edef\CHKL@verbopts{\CHKL@verbopts,firstline=3}}
\define@key{CHKL@envkeys}{hide}[]{\CHKL@showcodefalse}
\define@key{CHKL@envkeys}{withresult}[]{\CHKL@withresulttrue}
\define@key{CHKL@envkeys}{withoutresult}[]{\CHKL@withresultfalse}
\define@key{CHKL@envkeys}{showproblems}[]{\CHKL@showproblemstrue}
\define@key{CHKL@envkeys}{hideproblems}[]{\CHKL@showproblemsfalse}
%    \end{macrocode}
%
% \begin{macro}{\chklistingmsg}
% This macro takes a single argument \meta{label}.
% It first configures the |listings| and |fancyvrb| packages with the 
% current display options.
% It then checks the |fancyvrb| saved text namespace 
% (`\texttt{FV@SV@\ldots}') for an entry named `\texttt{\ldots 
% CHKL@MSG@\meta{label}}'.
% If found, the associated verbatim text is inserted via the |\UseVerbatim| 
% feature of |fancyvrb|, otherwise an error message is inserted.
% In the latter case, we prefer not to fail outright, because the user may 
% not yet have had the chance to run the compiler on the extracted code, in 
% which case the log will already contain warnings from |chklisting|.
% By convention, the |chklisting| environment creates an entry for the 
% empty label (`\texttt{FV@SV@CHKL@MSG@}') when compilation succeeds.
%    \begin{macrocode}
\DeclareRobustCommand{\chklistingmsg}[1]{
   \bgroup%
   \ifx\CHKL@msglst\CHKL@emptyoption\else
      \expandafter\lstset\expandafter{\CHKL@msglst,fancyvrb=true}\fi%
   \@ifundefined{FV@SV@CHKL@MSG@#1}
     {\def\@tempa{#1}
      \ifx\@tempa\empty
        \CHKL@none
      \else
        $\langle$No message found for the label `#1'!$\rangle$
      \fi}
     {\expandafter\UseVerbatim\expandafter[\CHKL@msgstyle]{CHKL@MSG@#1}}%
   \egroup}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\chklistingerr}
% This macro is essentially the same as the previous one---only that the 
% substring `\texttt{ERR}' is used instead of `\texttt{MSG}'.
%    \begin{macrocode}
\DeclareRobustCommand{\chklistingerr}[1]{
   \bgroup%
   \ifx\CHKL@errlst\CHKL@emptyoption\else
      \expandafter\lstset\expandafter{\CHKL@errlst,fancyvrb=true}\fi%
   \@ifundefined{FV@SV@CHKL@ERR@#1}
     {\def\@tempa{#1}
      \ifx\@tempa\empty
        \CHKL@none
      \else
        $\langle$No message found for the label `#1'!$\rangle$
      \fi}
     {\expandafter\UseVerbatim\expandafter[\CHKL@errstyle]{CHKL@ERR@#1}}%
   \egroup}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{chklisting}
% This is the main environment for including source code.
% This macro works in two parts:
% \begin{enumerate}
% \item
% It uses the listings package to write the code to a file,
% \item
% It either loads the corresponding |.tex| file or logs an error message.
% \end{enumerate}
%
% The |listings| package allows the definition of custom verbatim 
% environments.
% This one has a single argument (a list of |keyval| options).
%
%    \begin{macrocode}
\lstnewenvironment{chklisting}[1][]
  {%
%    \end{macrocode}
% Set default parameter values before invoking |\setkeys|:
%    \begin{macrocode}
    \CHKL@shouldfailfalse%
    \CHKL@showcodetrue%
    \let\CHKL@label\@undefined%
    \edef\CHKL@continue{}%
    \def\CHKL@skip{\CHKL@pkg@globalskip}%
    \let\CHKL@verbopts\CHKL@pkg@verbopts%
    \def\@currentlabel{\thechklisting}%
    \setkeys{CHKL@envkeys}{#1}%
%    \end{macrocode}
%
% Log an entry to the |.chkl| file:
%
%    \begin{macrocode}
    \CHKL@logsample{\arabic{chklisting}}{\CHKL@continue%
      \space\ifnum\CHKL@skip>0[skip=\CHKL@skip]\fi%
      \ifCHKL@shouldfail\space[fail]\fi}%
%    \end{macrocode}
%
% Update |\CHKL@precontinue| for the next source code block, and, if a label 
% was defined, add an |\CHKL@deps@|\meta{label} entry.
%
%    \begin{macrocode}
    \global\edef\CHKL@precontinue{\CHKL@continue\space\arabic{chklisting}}%
    \@ifundefined{CHKL@label}{}{%
    \global\expandafter\edef\csname CHKL@deps@\CHKL@label\endcsname{\CHKL@precontinue}}%
%    \end{macrocode}
%
% A file will be created in the |\CHKL@subdir| subdirectory, with the name 
% |\CHKL@prefix| followed by the value of the |chklisting| counter, padded 
% out with zeroes to four digits, and the extension |\RBRB@ext|.
%
%    \begin{macrocode}
    \edef\CHKL@num{%
        \ifnum\value{chklisting}<1000 0\fi
        \ifnum\value{chklisting}<100  0\fi
        \ifnum\value{chklisting}<10   0\fi
        \arabic{chklisting}}%
    \stepcounter{chklisting}%
    \def\CHKL@file{\CHKL@subdir/\CHKL@prefix\CHKL@num}%
%    \end{macrocode}
%
% Clear the definitions used to return information about the compilation 
% run, and close the environment by opening a file, using the |listings| 
% package, into which to write the ensuing contents.
%
%    \begin{macrocode}
    \global\let\chklistingcmd\@undefined%
    \global\let\FV@SV@ChkListingMsg\@undefined%
    \global\let\FV@SV@ChkListingErr\@undefined%
    \chklistingtrue%
    \setbox\@tempboxa\hbox\bgroup%
    \lst@BeginWriteFile{\CHKL@file\CHKL@ext}%
  }
%    \end{macrocode}
%
% Start closing the environment by closing the previously opened file and 
% group.
%
%    \begin{macrocode}
  {%
    \lst@EndWriteFile%
    \egroup%
%    \end{macrocode}
%
% If |hide| is not active, apply |\CHKL@verbopts| and reload the newly 
% created file.
%
%    \begin{macrocode}
    \ifCHKL@showcode%
        \bgroup%
        \ifx\CHKL@codelst\CHKL@emptyoption\else%
          \expandafter\lstset\expandafter{\CHKL@codelst,fancyvrb=true}%
        \fi%
        \expandafter\fvset\expandafter{\CHKL@verbopts}%
        \expandafter\VerbatimInput\expandafter[\CHKL@codestyle]{\CHKL@file\CHKL@ext}%
        \egroup%
    \fi%
%    \end{macrocode}
%
% Check whether a corresponding |.tex| file was created:
%
%    \begin{macrocode}
    \global\edef\CHKL@none{$\langle$Cannot load \CHKL@file.tex!$\rangle$}%
    \InputIfFileExists{\CHKL@file.tex}{\CHKL@fileexiststrue}{\CHKL@fileexistsfalse}%
%    \end{macrocode}
%
% If the |.tex| file was loaded successfully, create `unlabelled' saved 
% verbatim environments for the message and error texts.
% These are exploited, respectively, by the |\chklistingmsg| and 
% |\chklistingerr| macros.
%
%    \begin{macrocode}
    \ifCHKL@fileexists%
        \@ifundefined{FV@SV@ChkListingMsg}%
          {}{\global\let\FV@SV@CHKL@MSG@=\FV@SV@ChkListingMsg}%
        \@ifundefined{FV@SV@ChkListingErr}%
          {}{\global\let\FV@SV@CHKL@ERR@=\FV@SV@ChkListingErr}%
%    \end{macrocode}
%
% Then, if compilation failed and the |fail| option was not active, or if 
% compilation succeeded and the |fail| option is active, log a warning 
% message and, if errors are not being ignored, include details in the 
% document.
% Otherwise, if |withresult| was given, expand either |\chklistingerr| or 
% |\chklistingmsg|.
%
%    \begin{macrocode}
        \ifCHKL@shouldfail%
            \ifchklisting%
                \PackageWarning{checklistings}%
                    {Compilation of \CHKL@file\CHKL@ext\space should have failed}%
                \ifCHKL@showproblems%
                  \UseVerbatim[frame=single,
                               label=Unexpected success,
                               rulecolor=\color{red}]{ChkListingMsg}%
                \fi%
            \else%
                \ifCHKL@withresult%
                   {\setlength{\partopsep}{0em}\chklistingerr{}}%
                \fi%
            \fi%
        \else%
            \ifchklisting%
                \ifCHKL@withresult%
                   {%\vspace{\dimexpr-2\topsep-2\partopsep+.5em\relax}%
                    \setlength{\partopsep}{0em}\chklistingmsg{}}%
                \fi%
            \else%
                \PackageWarning{checklistings}%
                    {Compilation of \CHKL@file\CHKL@ext\space should not have failed}%
                \ifCHKL@showproblems%
                  \UseVerbatim[frame=single,
                               label=Unexpected failure,
                               rulecolor=\color{red}]{ChkListingErr}%
                \fi%
            \fi%
        \fi%
    \else%
%    \end{macrocode}
%
% If the |.tex| file was not loaded successfully, clear the 
% |\chklistingcmd| macros, and the `unlabelled' saved verbatim environments 
% for the message and error results.
%
%    \begin{macrocode}
        \PackageWarning{checklistings}{Cannot load \CHKL@file.tex}%
        \global\let\chklistingcmd\CHKL@none%
        \global\let\FV@SV@CHKL@MSG@\@undefined%
        \global\let\FV@SV@CHKL@ERR@\@undefined%
    \fi%
% If this environment is labelled, create persistent references to the saved 
% verbatim environments for the message and error results.
% These are exploited, respectively, by the |\chklistingmsg| and 
% |\chklistingerr| macros when their \meta{label} argument is not empty.
%
    \@ifundefined{CHKL@label}{}{%
      \global\expandafter\let%
        \csname FV@SV@CHKL@MSG@\CHKL@label\endcsname=\FV@SV@CHKL@MSG@%
      \global\expandafter\let%
        \csname FV@SV@CHKL@ERR@\CHKL@label\endcsname=\FV@SV@CHKL@ERR@%
    }%
  }%
%    \end{macrocode}
% \end{environment}
%
\makeatother
\clearpage
% \Finale
\endinput
