fpc/docs/packages/listings/listings.dtx
1999-06-08 08:53:07 +00:00

7112 lines
273 KiB
TeX

% \iffalse
%
% NOTE: This file contains very long lines (upto approx 270 characters).
% I haven't wrapped them since I won't do that by hand and haven't
% written any program doing the work.
%
% If you want to read this .dtx file, you might get in trouble with
% such long lines!
%
%
% S O F T W A R E L I C E N S E
% =================================
%
% The files listings.dtx and listings.ins and all files generated
% from only these two files are referred as 'the listings package' or
% simply 'the package'. A driver file is any file generated mainly from
% lstdrvrs.dtx.
%
% Copyright.
% The listings package is copyright 1996--1998 Carsten Heinz.
% The driver files are copyright 1997, 1998 or 1997--1998 any
% individual author listed in these files.
%
% Distribution.
% The listings package as well as lstdrvrs.dtx and all driver files
% are distributed freely. You are not allowed to take money for the
% distribution, except for a nominal charge for copying etc..
%
% Use of the package.
% The listings package is free for any non-commercial use. Commercial
% use needs (i) explicit permission of the author of this package and
% (ii) the payment of a license fee. This fee is to be determined in
% each instance by the commercial user and the package author and is
% to be payed as donation to the LaTeX3 project.
%
% No warranty.
% The listings package as well as lstdrvrs.dtx and all driver files
% are distributed without any warranty, express or implied, as to
% merchantability or fitness for any particular purpose.
%
% Modification advice.
% Permission is granted to change the listings package as well as
% lstdrvrs.dtx. You are not allowed to distribute any changed version
% of the package or any changed version of lstdrvrs.dtx, neither under
% the same name nor under a different one. Tell the author of the
% package about your local changes: other users will welcome removed
% bugs, new features and additional programming languages.
%
% Contacts.
% Send comments and ideas on the package, error reports and additional
% programming languages to
%
% Carsten Heinz
% Tellweg 6
% 42275 Wuppertal
% Germany
%
% or preferably to
%
% cheinz@gmx.de
%
% Trademarks
% appear throughout this documentation without any trademark symbol,
% so you can't assume that a name is free. There is no intention of
% infringement; the usage is to the benefit of the trademark owner.
%
% end of software license
%
%<*driver>
\documentclass{ltxdoc}
\usepackage[doc]{listings}[1998/11/09]
\newif\iffancyvrb
\IfFileExists{fancyvrb.sty}
{\fancyvrbtrue \usepackage{fancyvrb}}
{\fancyvrbfalse}
\EnableCrossrefs
\CodelineIndex
\OldMakeindex
\OnlyDescription
\begin{document}
\DocInput{listings.dtx}
\end{document}
%</driver>
% \fi ^^A balance the \iffancyvrb! :-)
% \fi
%
%
% \makeatletter
%^^A
%^^A A modified `environment' environment
%^^A
%\def\aspect{^^A
% \def\SpecialMainEnvIndex##1{^^A
% \@bsphack ^^A
% \index{aspects:\levelchar{\protect\ttfamily##1}\encapchar main}^^A
% \@esphack}^^A
% \begingroup \catcode`\\12 \MakePrivateLetters ^^A
% \m@cro@ \iffalse}
%\let\endaspect\endmacro
%
%^^A
%^^A We define a sample environment. All material between
%^^A \begin{lstsample} and \end{lstsample} is executed
%^^A 'on the left side' and typeset verbatim on the right.
%^^A
%^^A The environment is *not* designed for purposes other than
%^^A this documentation.
% \lst@Environment{lstsample}[1]\is
% {\gdef\lst@sample{#1}^^A
% \lst@BeginWriteFile{listings.tmp}^^A
% \def\lst@BOLGobble##1{}}^^A to gobble each first %
% {\lst@EndWriteFile ^^A
%^^A We execute the code resp. typset it verbatim (= empty language
%^^A with \ttfamily).
% \begin{center}
% \small ^^A \lstCC@Let{`\^^M}\space ^^A
% \begin{minipage}{0.45\linewidth}^^A
% \MakePercentComment\lst@sample
% \input{listings.tmp}\MakePercentIgnore^^A
% \end{minipage}
% \qquad
% \begin{minipage}{0.45\linewidth}
% \lstset{language={},style={},basicstyle=\ttfamily,baseem=0.51}^^A
% \hbox to \linewidth{\lstbox\lstinputlisting{listings.tmp}\hss}
% \end{minipage}
% \end{center}}
%
%^^A
%^^A We redefine the appearance of part, section, ...
%^^A
%\def\@part[#1]#2{\addcontentsline{toc}{part}{#1}%
% {\parindent\z@ \raggedright \interlinepenalty\@M
% \normalfont \huge \bfseries #2\markboth{}{}\par}%
% \nobreak\vskip 3ex\@afterheading}
%\renewcommand*\l@section[2]{%
% \ifnum \c@tocdepth >\z@
% \addpenalty\@secpenalty
% \addvspace{.25em \@plus\p@}%
% \setlength\@tempdima{1.5em}%
% \begingroup
% \parindent \z@ \rightskip \@pnumwidth
% \parfillskip -\@pnumwidth
% \leavevmode ^^A \bfseries
% \advance\leftskip\@tempdima
% \hskip -\leftskip
% #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par
% \endgroup
% \fi}
%\renewcommand*\l@subsection{\@dottedtocline{2}{1.5em}{2.3em}}
%\renewcommand*\l@subsubsection{\@dottedtocline{3}{3.8em}{3.2em}}
%\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
% {1.25ex \@plus1ex \@minus.2ex}%
% {-1em}%
% {\normalfont\normalsize\bfseries}}
%
%^^A
%^^A Suppress warning
%^^A
% \let\lstenv@DroppedWarning\relax
% \makeatother
%
%^^A
%^^A The following definitions come in handy soon.
%^^A There will be more in future.
%^^A
% \newcommand\lsthelper[4]{#1\ifx\empty#2\empty\typeout{^^JWarning: #1 has unknown email^^J}\else\space\texttt{<#2>}{}\fi}
% \newcommand\lstthanks[2]{#1\ifx\empty#2\empty\typeout{^^JWarning: #1 has unknown email^^J}\fi}
% \newcommand\lst{\texttt{lst}}
% \lstdefinelanguage[doc]{Pascal}{^^A
% keywords={alfa,and,array,begin,boolean,byte,case,char,const,div,^^A
% do,downto,else,end,false,file,for,function,get,goto,if,in,^^A
% integer,label,maxint,mod,new,not,of,or,pack,packed,page,program,^^A
% procedure,put,read,readln,real,record,repeat,reset,rewrite,set,^^A
% text,then,to,true,type,unpack,until,var,while,with,write,writeln},^^A
% sensitive=false,^^A
% doublecomment={(*}{*)}{\{}{\}},^^A
% stringizer=[d]{'}}^^A
% \lstset{defaultdialect=[doc]Pascal}
% \lstset{language=Pascal}
%
%
%^^A
%^^A The long awaited beginning of documentation
%^^A
% \newbox\abstractbox
% \setbox\abstractbox=\vbox{
% \begin{abstract}
% Listings.dtx is a source code printer for \LaTeX\ --- which always means \LaTeXe\ in this documentation.
% You can typeset stand alone files as well as enter listings using an environment similar to \texttt{verbatim} as well as you can print fragments using a command similar to |\verb|.
%^^A Since listings.dtx is a package and not a cross compiler, all listings are up to date without maintaining differences between (changed) source files and cross compiled files.
% The package supports a wide spectrum of programming languages --- some come already with \texttt{lstdrvrs.dtx}.
% Finally: Many parameters control the output.
% \end{abstract}}
%
% \title{{Listings.dtx} Version {0.19}}
% \author{Copyright 1996--1998 Carsten Heinz}
% \date{\box\abstractbox}
%
% \makeatletter\@twocolumntrue\makeatother
% \maketitle
% {\makeatletter\@starttoc{toc}}
%\iftrue
% \vfill
% \noindent \textbf{Again incompatibilities!}
% And there are certainly teething troubles since the complete kernel has been rewritten.
% So read this manual with care.
%\fi
% \onecolumn
%
%
% \part{User's guide}
%
%
% \section{Preface}
%
% The files \texttt{listings.dtx} and \texttt{listings.ins} and all files generated from only these two files are referred as 'the \textsf{listings} package' or simply 'the package'.
% A driver file is any file generated mainly from \texttt{lstdrvrs.dtx}.
%
% \paragraph{Alternatives.}
% The \textsf{listings} package is certainly not the final utility for typesetting source code listings.
% Other programs do their jobs very well if you are not satiesfied with \textsf{listings}.
% I should mention \textsf{a2ps} and the \textsf{LGrind} package.
% Let me know if you're using none of these solutions; I'd like to extend my suggestions.
%
% \paragraph{Reading this manual.}
% In any case you should read section ''\emph{\ref{uGettingStarted}. Getting started}'' step by step.
% You either start from the scratch there or you get in touch with the new user interface and other changes.
% That section is an introduction and doesn't cover all of the \textsf{listings} package, but the most common.
% After reading it you are prepared for the main reference if you need more details, more control or more features.
%
% \paragraph{Sorry!}
% On 1998/11/02 I decided to make major changes to the user interface, which were planned for version 0.2.
% But it's better to get the interface stable as soon as possible.
% In particular I must say sorry to all people I posted a pre-version of \textsf{listings} 0.19.
%
% \paragraph{Thanks.}
% There are many people I have to thank for fruitful communication, posting their ideas, giving error reports (first bug finder is listed), adding programming languages to \texttt{lstdrvrs.dtx}, etc..
% If you want to know that in detail, search for the names in the implementation part.
%^^A
%^^A Thanks for error reports (first bug finder only), new programming languages, etc.
%^^A Special thanks for communication which lead to kernel extensions.
%^^A
% Special thanks go to (alphabetical order)
% \begin{quote}
% \hyphenpenalty=10000\relax \rightskip=0pt plus \linewidth\relax
% \lstthanks{Andreas~Bartelt}{Andreas.Bartelt@Informatik.Uni-Oldenburg.DE},
% \lstthanks{Jan~Braun}{Jan.Braun@tu-bs.de},
% \lstthanks{Denis~Girou}{Denis.Girou@idris.fr},
% \lstthanks{Arne~John~Glenstrup}{panic@diku.dk},
% \lstthanks{Rolf~Niepraschk}{NIEPRASCHK@PTB.DE},
% \lstthanks{Rui~Oliveira}{rco@di.uminho.pt} and
% \lstthanks{Boris~Veytsman}{boris@plmsc.psu.edu}.
% \end{quote}
% Moreover I wish to thank
% \begin{quote}
% \hyphenpenalty=10000\relax \rightskip=0pt plus \linewidth\relax
% \lstthanks{Bj{\o}rn~{\AA}dlandsvik}{bjorn@imr.no},
% \lstthanks{Gaurav~Aggarwal}{gaurav@ics.uci.edu},
% \lstthanks{Kai~Below}{below@tu-harburg.de},
% \lstthanks{Detlev~Dr\"oge}{droege@informatik.uni-koblenz.de},
% \lstthanks{Anders~Edenbrandt}{Anders.Edenbrandt@dna.lth.se},
% \lstthanks{Harald~Harders}{h.harders@tu-bs.de},
% \lstthanks{Christian~Haul}{haul@dvs1.informatik.tu-darmstadt.de},
% \lstthanks{J\"urgen~Heim}{heim@astro.uni-tuebingen.de},
% \lstthanks{Dr.~Jobst~Hoffmann}{HOFFMANN@rz.rwth-aachen.de},
% \lstthanks{Knut~M\"uller}{knut@physik3.gwdg.de},
% \lstthanks{Zvezdan~V.~Petkovic}{zpetkovic@acm.org},
% \lstthanks{Michael~Piotrowski}{mxp@linguistik.uni-erlangen.de},
% \lstthanks{Ralf~Quast}{rquast@hs.uni-hamburg.de},
% \lstthanks{Aslak~Raanes}{araanes@ifi.ntnu.no},
% \lstthanks{Detlef~Reimers}{dreimers@aol.com},
% \lstthanks{Magne~Rudshaug}{magne@ife.no},
% \lstthanks{Andreas~Stephan}{astepha@wmpi04.math.uni-wuppertal.de},
% \lstthanks{Dominique~de~Waleffe}{ddw@miscrit.be},
% \lstthanks{Herbert~Weinhandl}{weinhand@grz08u.unileoben.ac.at},
% \lstthanks{J\"orn~Wilms}{wilms@rocinante.colorado.edu} and
% \lstthanks{Kai~Wollenweber}{kai@ece.WPI.EDU}.
% \end{quote}
%
%^^A \lsthelper{Andreas Bartelt}{Andreas.Bartelt@Informatik.Uni-Oldenburg.DE}{1997/09/11}{single line comes out using \inputlisting inside \fbox}
%^^A \lsthelper{Michael Piotrowski}{mxp@linguistik.uni-erlangen.de}{1997/11/04}{! Use of \lstdrv@perl@TestCommentCut doesn't match its definition^^J\lst@line ->I^^JRF::LangID -- Statistical identification of language for IRF/1^^J^^J(POD ist Zeile '=irgendwas' bis Zeile '=cut')}
%^^A \lsthelper{Bj{\o}rn {\AA}dlandsvik}{bjorn@imr.no}{1997/10/27}{listings.sty is incompatible to inputenc.sty}
%
%
% \section{Software license}
%
% \paragraph{Copyright.}
% The \textsf{listings} package is copyright 1996--1998 Carsten Heinz.
% The driver files are copyright 1997, 1998 or 1997--1998 any individual author listed in these files.
%
% \paragraph{Distribution.}
% The \textsf{listings} package as well as \texttt{lstdrvrs.dtx} and all driver files are distributed freely.
% You are not allowed to take money for the distribution, except for a nominal charge for copying etc..
%
% \paragraph{Use of the package.}
% The \textsf{listings} package is free for any non-commercial use.
% Commercial use needs (i) explicit permission of the author of this package and (ii) the payment of a license fee.
% This fee is to be determined in each instance by the commercial user and the package author and is to be payed as donation to the \LaTeX3 project.
%
% \paragraph{No warranty.}
% The \textsf{listings} package as well as \texttt{lstdrvrs.dtx} and all driver files are distributed without any warranty, express or implied, as to merchantability or fitness for any particular purpose.
%
% \paragraph{Modification advice.}
% Permission is granted to change the \textsf{listings} package as well as \texttt{lstdrvrs.dtx}.
% You are not allowed to distribute any changed version of the package or any changed version of \texttt{lstdrvrs.dtx}, neither under the same name nor under a different one.
% Tell the author of the package about your local changes: other users will welcome removed bugs, new features and additional programming languages.
%
% \paragraph{Contacts.}
% Send comments and ideas on the package, error reports and additional programming languages to \emph{Carsten Heinz, Tellweg 6, 42275 Wuppertal, Germany} or preferably to \texttt{cheinz@gmx.de}.
%
% \paragraph{Trademarks}
% appear throughout this documentation without any trademark symbol, so you can't assume that a name is free.
% There is no intention of infringement; the usage is to the benefit of the trademark owner.
%
%
% \section{Getting started}\label{uGettingStarted}
%
%
% \iffalse
% \subsection{Installation}
%
% \begin{enumerate}
% \item You need \texttt{listings.dtx} and \texttt{listings.ins} to install the \textsf{listings} package.
% \texttt{lstdrvrs.dtx} contains some language drivers.
% Move \texttt{.dtx} and \texttt{.ins} files into a separate folder if you want to.
% \item Remove all \texttt{lst???.sty} files if you update from an earlier version.
% \item Run \texttt{listings.ins} through \TeX.
% This creates the kernel \texttt{listings.sty} and two interface files \texttt{lst017.sty} and \texttt{lstfvrb.sty}.
% If you have \texttt{lstdrvrs.dtx}, a configuration file \texttt{listings.cfg} and a couple of driver files are also generated.
% \item Copy all created \texttt{.sty} and \texttt{.cfg} files to a directory searched by \TeX.
% \end{enumerate}
% \fi
%
%
% \subsection{Package loading}
%
% As usual in \LaTeX\ the package is loaded by |\usepackage[|\meta{options}|]{listings}|, where |[|\meta{options}|]| is optional.
% Note that \textsf{listings} 0.19 needs more save stack size than any previous version.
% The following options are available:
% \begin{description}
% \item[\texttt{0.17}]
% Use this option to compile documents created with version 0.17 of the \textsf{listings} package.
% Note that you can't use old driver files and that the option does not guarantee full compatibility.
% If you want to polish up an old document, use this option together with new commands and keys.
% There shouldn't be many problems, but I haven't made deep tests.
% \item[\normalfont\texttt{index} and \texttt{procnames}] define the 'index' respectively 'procnames' aspect, whatever that means.
% \item[\normalfont\texttt{ndkeywords} and \texttt{rdkeywords}] define second respectively third order keywords.
% \end{description}
% Note: Each option slows down the package, so it becomes quite slow if you use all options, for example.
% Note also that you can't activate any optional feature after package loading --- except you're a hacker and read the implementation part.
%
% Here is some kind of minimal file.
% \begin{verbatim}
% \documentclass{article}
%
% \usepackage{listings}
% %\usepackage[ndkeywords,index]{listings}% with some options
%
% \begin{document}
%
% \lstset{language=Pascal}
% % Any example may be inserted here.
%
% \end{document}\end{verbatim}
% \label{uMinimalFile}It loads the \textsf{listings} package without any option, but shows how the package is loaded with index option and second order keywords.
% Moreover we select Pascal as programming language.
%
% If you need more than one programming language in your document, I recommend the preamble command |\lstloadlanguages|, which loads the given programming languages only, e.g.\ |\lstloadlanguages{Pascal,Fortran,C++}|.
% You find more details in section \ref{uLanguagesAndStyles}.
%
%
% \subsection{Typesetting listings}
%
% You can print (a) stand alone files, (b) source code from \texttt{.tex} files or (c) code fragments within a paragraph.
% The difference between (b) and (c) is something like between display and text formulas (|$$| and |$|).
%
% We begin with code fragments.
% If you want '\lstinline!var i:integer;!', you can simply write '|\lstinline!var i:integer;!|'.
% The exclamation marks delimit the code fragment.
% They could be replaced by any character not in the code fragment, i.e.\ '|\lstinline$var i:integer;$|' would produce the same output.
%
% The \texttt{lstlisting} environment typesets the source code in between.
% It has one parameter, which we leave empty for the moment.
% \begin{lstsample}{}
%\begin{lstlisting}{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%
%Write('Keywords are case ');
%WritE('insensitive here.');
%\end{lstlisting}
% \end{lstsample}
% \noindent
% Like most examples this shows the \LaTeX\ source code on the right and the result on the left.
% If you insert the \LaTeX\ code in the minimal file and run it through \TeX, the listing uses the whole text width.
%
% Finally examples for stand alone files:
% \begin{lstsample}{\lstset{baseem=0.5}}
%\lstinputlisting{listings.tmp}
% \end{lstsample}
% \noindent
% Do you wonder about the left hand side?
% Well, the file \texttt{listings.tmp} contains the current example.
% This is exactly the line you see on the right.
% If you want this line to be typeset in Pascal mode, you get what you've got.
% If you want the lines $3,4,\ldots,10$ of \texttt{testfile.pas}, write
% \begin{verbatim}
% \lstinputlisting[first=3,last=10]{testfile.pas}\end{verbatim}
% But be sure that the first line does exist, or you will get a ''runaway argument'' error.
%
% Problems could arise if you (try to) put a listing in a box, tabular environment or something similar.
% The |\lstbox| command in section \ref{uTypesettingListings} might solve this.
% If you use an extended character table in your listings, you must use the |extendedchars| key, see section \ref{uSomeSpecialKeys}.
%
%
% \subsection{The ''key=value'' interface}
%
% The \textsf{listings} package uses \textsf{keyval.sty} from the \textsf{graphics} bundle by David Carlisle.
% Each 'aspect' or 'parameter' you can control has an associated key.
% To select a programming language, for example, you need the key |language|, the sign |=| and the name of the language as value.
% The command |\lstset| gets this construction as argument.
% You have seen this in the minimal file on page \pageref{uMinimalFile}.
% You can set more than one parameter with a single |\lstset| if you separate two or more ''key=value'' constructions by commas:
% \begin{verbatim}
% \lstset{language=Pascal,keywordstyle=\bfseries}\end{verbatim}
% If the value itself contains a comma, you must enclose the value in braces:
% \begin{verbatim}
% \lstset{keywords={one,two,three}}\end{verbatim}
% |\lstset{keywords=one,two,three}| would set the one and only keyword |one| and gives an error message since the parameters |two| and |three| do not exist.
%
% Two final notes:
% (1) Some keys has default values, e.g.\ |flexiblecolumns=true| turns flexible columns on, but |flexiblecolumns| without any |=true| would do the same since the value true is default for that key.
% But you must use the value |false| if you want to turn them off.
% (2) |\lstset| sets the values local to the current group.
% Just forget it if you don't know what that means.
% The command |\lstinputlisting| (as seen above) and the environment (as you see below) both have optional arguments.
% If you use a key=value list as optional argument, these selections are valid for the particular listing only and the previous values are restored afterwards.
% For example, if the current language is Pascal, but you want \texttt{testfile.f95} from line 3 on, write
% \begin{verbatim}
% \lstinputlisting[first=3,language=Fortran]{testfile.f95}\end{verbatim}
% Afterwards Pascal is still the current language.
% Note that |\lstinline| has no optional parameter.
%
%
% \subsection{Figure out the appearance}
%
% Keywords are typeset bold, comments in italic shape and spaces in strings appear as '\textvisiblespace' (without the two quotes).
% You can change that default behaviour:
% \begin{verbatim}
%\lstset{
% basicstyle=\small, % print whole listing small
% keywordstyle=\bfseries\underbar,% 'underlined' bold keywords
% nonkeywordstyle={}, % nothing happens to other identifiers
% commentstyle=\itshape, % default
% stringstyle=\ttfamily, % typewriter font for strings
% blankstring=true} % blank spaces are blank in strings\end{verbatim}
% We typeset a previous example with these styles again.
%\lstset{basicstyle=\small,
% keywordstyle=\bfseries\underbar,nonkeywordstyle={},
% commentstyle=\itshape,stringstyle=\ttfamily,blankstring=true}
% \begin{lstsample}{}
%\begin{lstlisting}{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%
%Write('Keywords are case ');
%WritE('insensitive here.');
%\end{lstlisting}
% \end{lstsample}
% \noindent
% The style definitions above use two kind of commands; on the one hand |\ttfamily| or |\bfseries| taking no arguments and on the other |\underline|, which gets exactly one argument.
% The \emph{very last} token of |keywordstyle|, |nonkeywordstyle| and |labelstyle| (see below) \emph{may} be a macro getting exactly one argument, namely the (non)keyword or label.
% All other tokens \emph{must not} take any arguments --- or you will get deep in trouble.
% \lstset{style={},blankstring=false}
%
% \textbf{Warning:}
% You shouldn't use striking styles too often, but 'too often' depends on how many keywords the source code contains, for example.
% Your eyes would concentrate on the framed, bold red printed keywords only, and your brain must compensate this.
% Reading such source code could be very exhausting.
% If it were longer, the last example would be quite good in this sense.
% Believe me.
%
%
% \subsection{Line numbers}
%
% You want tiny line numbers each second line?
% Here you are:
% \begin{lstsample}{}
%\lstset{labelstyle=\tiny,% <===
% labelstep=2}% <===
%\begin{lstlisting}{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%
%Write('Keywords are case ');
%WritE('insensitive here.');
%\end{lstlisting}
% \end{lstsample}
% \noindent
% |labelstep=0| turns line numbering off.
% In the sequel we use |labelstyle=\tiny| and |labelstep=2|, even if it doesn't appear in the verbatim part.
% And now we try to interrupt (continue) a listing.
% For this purpose we use |{ }| as argument to the environment.
% \begin{lstsample}{\lstset{labelstyle=\tiny,labelstep=2}}
%\begin{lstlisting}{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%
%\end{lstlisting}
%
%And we continue the listing:
%
%\begin{lstlisting}{ }% <===
%Write('Keywords are case ');
%WritE('insensitive here.');
%\end{lstlisting}
% \end{lstsample}
% \noindent
% Note that the empty line at the end of the first part is not printed, but it is responsible for correct line numbering.
% |{ }| continued the previous '|{}|'-listing.
% In general the argument is the name of the listing.
% An empty (= |{}|) named listing always starts with line number one, no matter whether line numbers are printed or not.
% A space (= |{ }|) named listing continues the last empty or space named one.
% That's easy.
% And this mechanism becomes easier if you use real names for your listings.
% In that case all listings with the same name use a common line counter: the second (same named) listing continues automatically the first.
% Even if there are other listings in between.
% \begin{lstsample}{\lstset{labelstyle=\tiny,labelstep=2}}
%\begin{lstlisting}{Test}% <===
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%
%\end{lstlisting}
%
%And we continue the listing:
%
%\begin{lstlisting}{Test}% <===
%Write('Keywords are case ');
%WritE('insensitive here.');
%\end{lstlisting}
% \end{lstsample}
% \noindent
% The next |Test| listing goes on with line number {\makeatletter\lstno@Test}.
% Note that listing names are case sensitive.
%
%
% \subsection{Tabulators and form feeds}
%
% You might get some unexpected output if your source code contains a tabulator or form feed.
% The package assumes tabulator stops at columns 9,17,25,33,\ldots, and a form feed prints an empty line.
% This is predefined via
% \begin{verbatim}
% \lstset{tabsize=8,formfeed=\bigbreak}\end{verbatim}
% If you change the eight to the number $n$, you will get tabulator stops at columns $n+1,\allowbreak 2n+1,\allowbreak 3n+1,$ and so on.
% If you want a new page every form feed, use |formfeed=\newpage|.
% \lstset{tabsize=4}
% \begin{lstsample}{}
%\lstset{tabsize=4}
%\begin{lstlisting}{}
%123456789
% { one tabulator }
% { two tabs }
%123 { 123 and two tabs }
%\end{lstlisting}
% \end{lstsample}
% \lstset{tabsize=8}\noindent
% Unfortunately both sides are typeset with |tabsize=4|.
%
%
% \subsection{Indent the listing}
%
% The examples are typeset with centered \texttt{minipage}s.
% That's the reason why you can't see that line numbers are printed in the margin (default).
% Now we separate the 'minipage margin' and the minipage by a vertical rule:
% \begin{lstsample}{\lstset{frame=l,frametextsep=0pt,labelstyle=\tiny,labelstep=2}}
%Some text before
%\begin{lstlisting}{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%\end{lstlisting}
% \end{lstsample}
% \noindent
% The listing is lined up with the normal text.
% You can change this if you want.
% The parameter |indent| 'moves' the listing to the right (or left if the skip is negative).
% \begin{lstsample}{\lstset{frame=l,frametextsep=0pt,labelstyle=\tiny,labelstep=2}}
%Some text before
%\lstset{indent=2em}% <===
%\begin{lstlisting}{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%\end{lstlisting}
%
%\begin{lstlisting}{ }
%Write('Keywords are case ');
%WritE('insensitive here.');
%\end{lstlisting}
% \end{lstsample}
% \noindent
% Note that |\lstset{indent=2em}| also changes the indent for the second listings.
% If you want to indent a single listing only, use the argument of |\lstset| as optional argument to the listing environment:
% \begin{lstsample}{\lstset{frame=l,frametextsep=0pt,labelstyle=\tiny,labelstep=2}}
%\begin{lstlisting}[indent=2em]{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%\end{lstlisting}
%
%\begin{lstlisting}{ }
%Write('Keywords are case ');
%WritE('insensitive here.');
%\end{lstlisting}
% \end{lstsample}
% \noindent
% Such local changes apply to all supported parameters.
%
% If you use environments like \texttt{itemize} or \texttt{enumerate}, there is 'natural' indention coming from these environments.
% By default the \textsf{listings} package respects this.
% But you might use |wholeline=true| (or |false|) to make your own decision.
% \begin{lstsample}{\lstset{frame=l,frametextsep=0pt,labelstyle=\tiny,labelstep=2}}
%\begin{itemize}
%\item First item:
%
%\begin{lstlisting}{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%\end{lstlisting}
%
%\item Second item:
%\lstset{wholeline=true}% <===
%\begin{lstlisting}{ }
%Write('Keywords are case ');
%WritE('insensitive here.');
%\end{lstlisting}
%\end{itemize}
% \end{lstsample}
% \noindent
% You can use |wholeline| together with |indent|, of course.
% Refer section \ref{uListingAlignment} for a description of |spread|.
%
%
% \subsection{Fixed and flexible columns}
%
% The first thing a reader notices is --- except different styles for keywords etc. --- the column alignment of a listing.
% The problem: I don't like listings in typewriter fonts and other fonts need not to have a fixed width.
% But we don't want
% \begin{itemize}\item[]\begin{tabular}{@{}l}
% if\ x=y\ then\ write('alignment')\\
% \ \ \ \ \ \ \ else\ print('alignment');
% \end{tabular}\end{itemize}
% only because spaces are not wide enough.
% There is a simple trick to avoid such things.
% We make boxes of the same width and put one character in each box:
% \def\docharfbox#1#2{\fbox{\hbox to#1em{\hss\vphantom{fy}#2\hss}}}
% \def\docharbox#1#2{\hbox to#1em{\hss#2\hss}}
% \begin{itemize}\item[]
% \def\makeboxes#1{\docharfbox1#1\ifx#1\relax\else\expandafter\makeboxes\fi}
% \makeboxes if\ x=y\ then\ write\relax\space\ldots\\
% \makeboxes \ \ \ \ \ \ \ else \ print\relax\space\ldots
% \end{itemize}
% Going this way the alignment of columns can't be disturbed.
% \def\makeboxes#1{\docharbox{0.45}#1\ifx#1\relax\else\expandafter\makeboxes\fi}
% But if the boxes are not wide enough, we get '\makeboxes if\ x=y\ then\relax\ldots', and choosing the width so that the widest character fits in leads to
% \def\makeboxes#1{\docharbox{1}#1\ifx#1\relax\else\expandafter\makeboxes\fi}
% '\makeboxes if\ x=y\ then\ write\relax\ldots'.
% Both are not acceptable.
% Since all input will be cut up in units, we can put each unit in a box, which width is multiplied by the number of characters we put in, of course.
% The result is
% \def\makeboxes#1#2{\docharfbox{#1}{#2}\ifx#2\relax\else\expandafter\makeboxes\fi}
% \makeboxes{1.4}{i\hss f}{.7}{\ }{.7}{x}{.7}{=}{.7}{y}{.7}{\ }{2.8}{t\hss h\hss e\hss n}{.7}{\ }{3.5}{w\hss r\hss i\hss t\hss e}{.7}\relax\space.
% Since we put wide and thin characters in the same box, the width of a single character box need not to be the width of the widest character.
% The empirical value {\makeatletter\lst@baseemfixed}em (which is called 'base em' later) is a compromise between overlapping characters and the number of boxes not exceeding the text width, i.e.\ how many characters fit a line without getting an overfull |\hbox|.
%
% \begingroup
% But overlapping characters are a problem if you use many upper case letters, e.g.\ \docharbox{3}{W\hss O\hss M\hss E\hss N} --- blame me and not the women, in fact \docharbox{1.8}{M\hss E\hss N} doesn't look better.
% To go around this problem the \textsf{listings} package supports more 'flexible columns' in contrast to the fixed columns above.
% Arne John Glenstrup (whose idea the format is) pointed out that he had good experience with flexible columns and assembler listings.
% The differences can be summed up as follows: The fixed column format ruins the nice spacing intended by the font designer, and the flexible format ruins the column alignment (possibly) intended by the programmer.
% We illustrate that:
% \lstset{style={},language={}}
% \def\sample{\begin{lstlisting}{}^^J\ WOMEN\ \ are^^J \ \ \ \ \ \ \ MEN^^J WOMEN are^^J better MEN^^J \end{lstlisting}}
% \begin{center}\begin{tabular}{c@{\qquad\quad}c@{\qquad\quad}c}
% verbatim&fixed columns&flexible columns\\
% &with {\makeatletter\lst@baseemfixed}em&with {\makeatletter\lst@baseemflexible}em\\ \noalign{\medskip}
% \setkeys{lst}{basicstyle=\ttfamily,baseem=0.51}\lstbox\sample&\lstset{flexiblecolumns=false}\lstbox\sample&\lstset{flexiblecolumns=true}\lstbox\sample\lstset{flexiblecolumns=false}
% \end{tabular}\end{center}
% Hope this helps.
% Note the varying numbers of spaces between 'WOMEN' and 'are' and look at the different outputs.
% The flexible column format typesets all characters at their natural width.
% In particular characters never overlap.
% If a word needs more space than reserved ('WOMEN'), the rest of the line moves to the right.
% Sometimes a following word needs less space than reserved, or there are spaces following each other.
% Such 'surplus' space is used to fix the column alignment:
% The blank space in the third line have been printed properly, but the two blanks in the first line have been printed as one blank space.
% We can show all this more drastic if we reduce the width of a single character box:
% \begin{center}\lstset{baseem={0.3,0.0}}\begin{tabular}{c@{\qquad\quad}c@{\qquad\quad}c}
% &{\makeatletter\lst@baseemfixed}em&{\makeatletter\lst@baseemflexible}em\\ \noalign{\medskip}
% \setkeys{lst}{basicstyle=\ttfamily,baseem=0.51}\lstbox\sample&\lstset{flexiblecolumns=false}\lstbox\sample&\lstset{flexiblecolumns=true}\lstbox\sample\lstset{flexiblecolumns=false}
% \end{tabular}\end{center}
% In flexible column mode the first 'MEN' moves to the left since the blanks before are $7\cdot 0.0$em$=0$em wide.
% Even in flexible mode you shouldn't reduce 'base em' to less than 0.33333em ($\approx$ width of a single space).
% \endgroup
%
% You want to know how to select the flexible column format and how to reset to fixed columns?
% Try |flexiblecolumns=true| and |flexiblecolumns=false|.
%
%
% \subsection{Selecting other languages}\label{uSelectingOtherLanguages}
%
% You already know that |language=|\meta{language name} selects programming languages --- at least Pascal and Fortran.
% But that's not the whole truth.
% Both languages know different dialects (= version or implementation), for example Fortran 77 and Fortran 90.
% You can choose such special versions with the optional argument of |language|.
% Write
% \begin{verbatim}
% \lstset{language=[77]Fortran}% Fortran 77
% \lstset{language=[XSC]Pascal}% Pascal XSC\end{verbatim}
% to select Fortran 77 and Pascal XSC, respectively.
%
% We give a list of all languages and dialects supported by \texttt{lstdrvrs.dtx}.
% Use the given names as (optional) values to |language|.
% An 'empty' language is also defined: |\lstset{language={}}| detects no keywords, no comments, no strings, \ldots
% \begin{center}
% \begin{tabular}{ll}
% Ada & Lisp \\
% Algol (|68|,|60|) & Logo \\
% C (|ANSI|,|Objective|)& Matlab \\
% Cobol (|1985|,|1974|,|ibm|) & Mercury \\
% Comal 80 & Modula-2 \\
% C++ (|ANSI|,|Visual|) & Oberon-2 \\
% csh & Pascal (|Standard|,|XSC|,|Borland6|) \\
% Delphi & Perl \\
% Eiffel & PL/I \\
% Elan & Prolog \\
% Euphoria & Simula (|67|,|CII|,|DEC|,|IBM|) \\
% Fortran (|95|,|90|,|77|) & SQL \\
% IDL & TeX (|plain|,|primitive|,|LaTeX|,|alLaTeX|) \\
% HTML & VHDL \\
% Java
% \end{tabular}
% \end{center}
% The configuration file \texttt{listings.cfg} defines each first dialect as default dialect, i.e.\ |\lstset{language=C}| selects ANSI C.
% After
% \begin{verbatim}
% \lstset{defaultdialect=[Objective]C}\end{verbatim}
% Objective-C becomes default dialect for C, but the language is \emph{not} selected with that command.
%
% \medskip
% Remark: The driver files define the languages with |\lstdefinelanguage|.
% The languages have all 'bugs' coming from the language commands, e.g.\ in Ada and Matlab it is still possible that the package assumes a string where none exists.
% See \texttt{lstdrvrs.dtx} for more remarks on special programming languages.
%
%
% \section{Main reference}
%
% \newcommand\UTODO[1]{}
% \newenvironment{TODO}{\begin{quote}\footnotesize To do:}{\end{quote}}
% \newenvironment{macrosyntax}
% {\list{}{\itemindent-\leftmargin\labelsep=0pt\relax %
% \def\makelabel##1{\lstmklab##1,\relax}}}
% {\endlist}
% \def\lstmklab#1,#2\relax{%
% \ifx\empty#2\empty %
% \lstmklabb#1,,\relax %
% \else
% \lstmklabb#1,#2\relax %
% \fi}
% \def\lstmklabb#1,#2,\relax{%
% \llap{\scriptsize\itshape#2}%
% \rlap{\hskip-\itemindent\hskip\labelwidth\hskip\linewidth#1}}
%
% In this section we list all user environments, commands and keys together with their parameters and possible values.
% Sometimes there are examples or more detailed information at the end of the subsections.
% All user macros have the prefix \lst.
% This avoids naming conflicts with other packages or document classes.
%
% In the sequel the label \emph{changed} indicates any change in behaviour or syntax of a command, environment or key, so read these items carefully.
% Keys strongly related to special programming languages have the label \emph{lang.spec.}.
% Usually they are available only if you have loaded the corresponding programming language.
% All other labels should be clear.
% The numbers in the right margin give the version number of introduction (either as internal or as user macro/key).
%
% Note that commands, environments and keys can be distinguished easily:
% A command begins with a backslash and a key is presented in ''|key=|\meta{value}'' fashion.
% All the rest are environments, which is in fact a single one.
%
%
% \subsection{Typesetting listings}\label{uTypesettingListings}
%
% \begin{macrosyntax}
% \item[0.1,changed] |\lstinputlisting[|\meta{key=value list}|]{|\meta{file name}|}|
%
% typesets the source code file using the active language and style (locally modified by the key=value list).
% Empty lines at the end of listing are dropped.
%
% The keys |first| and |last| determines the printed line range.
% Default is \emph{always} 1--9999999, where 'always' means that you can't set |first| and |last| globally.
% If you don't want a whole file, you must specify the line range.
% The example |\lstinputlisting[first=3,last=10]{testfile.pas}| would print lines 3,4,\ldots,10 of \texttt{testfile.pas} if file and lines are present.
%
% The boolean key |print| controls whether or not |\lstinputlisting| typesets a listing:
% |print=false| speed up things for draft versions of your document and |print=true| typesets the stand alone files.
%
% Note: The keys |first|, |last| and |print| only apply to |\lstinputlisting|.
%^^A
%^^A TODO: That's not true.
%^^A The key |first| also applies to lstlisting.
%^^A It sets the line number of the first line.
%^^A
%
% \item[0.15,changed] |lstlisting[|\meta{key=value list}|]{|\meta{name}|}|
%
% typesets source code between |\begin{lstlisting}{|\meta{name}|}| (+ line break) and |\end{lstlisting}|, but empty lines at the end of listing are dropped.
% Characters on the same line as the end of environment are \emph{not} dropped, i.e.\ source code right before and \LaTeX\ code after the end of environment is typeset respectively executed.
% If \meta{name} is not empty and the listing is not continued, the name appears in the list of listings.\\
% Same named listings have common line counter, i.e.\ the second (same named) listing continues the first, the third continues the second, and so on.
% There are two exceptions: An empty named listing always starts with line number 1 and is continued with listings named |{ }| (single blank space).
%
% The key |resetlineno| (given without any value) sets the line number of the first line to 1.
% You can also specify a number, e.g.\ |resetlineno=10|.
% |advancelineno=|\meta{number} advances the number of the first line by \meta{number}.
% These two keys take also effect on |{}| and |{ }| named listings.
%
% Note: The keys |resetlineno| and |advancelineno| only apply to the environment and must be used in the optional key=value list.
%
% \item[0.18,new] |\lstinline|
%
% works like |\verb|, but uses the active language and style, of course.
% You can write '|\lstinline!var i:integer;!|' and get '\lstinline!var i:integer;!'.
% Note that these listings always use flexible columns and that |\lstinline| has no optional key=value list.
%\UTODO{implement optional key=value list}
%
% \item[0.18,new] |\lstbox[|\meta{b$\vert$c$\vert$t}|]|
%
% is used right before |\lstinputlisting| or a listing environment.
% Without |\lstbox| the listing uses a new paragraph and the complete line width, even if the listing is one character wide.
% |\lstbox| returns the listing as a |\hbox|, which has the necessary width only (line numbers possibly not included).
% Use this command within explicit |\hbox|es, |$$|\ldots|$$|, etc..
% The optional argument gives the vertical position of the listing: bottom, center (default) or top.
% \end{macrosyntax}
%
%
% \subsection{List of listings}
%
% \begin{macrosyntax}
% \item[0.16] |\listoflistings|
%
% prints a list of listings.
% The names are the file names or names of the listings.
%
% \item[0.16] |\listlistingsname|
%
% contains the header name, which is 'Listings' by default.
% You may adjust it via |\renewcommand\listlistingsname{whatever}|.
%
% \item[0.19,new] |\lstname|
%
% contains the name of the current (last) listing in \emph{printable} form.
% After |pre=\subsubsection{\lstname}| each listing begins a new subsubsection, which name is the listing name.
% The key |pre| is described in section \ref{uSomeSpecialKeys}.
% You can also use it to index all listings, but then you must expand the content first.
% Simply write |\expandafter\index\expandafter{\lstname}| (as value to |pre| if you want).
%
% \item[0.19,new] |\lstintname|
%
% contains the name of the current (last) listing possibly in nonprintable form.
% Use this macro inside |\label| and |\ref| for example.
% But be aware that a reference counter must be defined --- or the label is the current section, subsection, and so on.
% You might use it like this:
% \begin{verbatim}
% \lstset{pre=\caption{\lstname}\label{lst\lstintname}}
%
% \begin{figure}
% \begin{lstlisting}{Empty}
% \end{lstlisting}
% \end{figure}
%
% Figure \ref{lstEmpty} shows an empty listing.\end{verbatim}
% Here \emph{all} listings get a caption and a label (unless |pre| is redefined).
% \end{macrosyntax}
%
%
% \subsection{Basic style keys}\label{uBasicStyleKeys}
%
% \begin{macrosyntax}
% \item[0.18,new] |basicstyle=|\meta{basic style and size}
% \item[0.11] |keywordstyle=|\meta{style for keywords}
% \item[0.19,new,optional] |ndkeywordstyle=|\meta{style for second keywords}
% \item[0.19,new,optional] |rdkeywordstyle=|\meta{style for third keywords}
% \item[0.18,new] |nonkeywordstyle=|\meta{style}
% \item[0.11] |commentstyle=|\meta{style}
% \item[0.12] |stringstyle=|\meta{style}
% \item[0.16] |labelstyle=|\meta{style}
%
% Each value of these keys determines the font and size (or more general style) in which special parts of a listing appear.
% The \emph{last} token of the (non,nd,rd) keyword and label style might be an one-parameter command like |\textbf| or |\underline|.
%
% \item[0.16,bug] |labelstep=|\meta{step}
%
% No line numbers are printed if \meta{step} is zero.
% Otherwise all lines with ''line number $\equiv 0$ modulo \meta{step}'' get a label, which appearance is controlled by the label style.
%
% Bug: If a comment (or string) goes over several lines, the line numbers (if on) also have comment (string) style.
% The easiest work-around is possibly the use of |\normalfont| in |\lstlabelstyle|.
%
% \item[0.12] |blankstring=|\meta{true$\vert$false}
%
% let blank spaces in strings appear as blank spaces respectively as \textvisiblespace.
% The latter is predefined.
%
% \item[0.12] |tabsize=|\meta{number}
%
% sets tabulator stops at columns $n+1$, $2n+1$, $3n+1$, etc. if $n=$\meta{number}.
% Each tabulator in a listing moves the current column to the next tabulator stop.
% It is initialized with |tabsize=8|.
%
% \item[0.19,new] |formfeed=|\meta{token sequence}
%
% Whenever a listing contains a form feed \meta{token sequence} is executed.
% It is initialized with |formfeed=\bigbreak|.
% \end{macrosyntax}
%
%
% \subsection{Fixed and flexible columns}
%
% \begin{macrosyntax}
% \item[0.18,new] |flexiblecolumns=|\meta{true$\vert$false}
%
% selects the flexible respectively the fixed column format.
%
% \item[0.16,addon] |baseem=|\meta{width in units of em}\quad or\quad|baseem={|\meta{fixed}|,|\meta{flexible mode}|}|
%
% sets the width of a single character box for fixed and flexible mode (both to the same value or individually).
% It's pre-defined via |baseem={|{\makeatletter\lst@baseemfixed}|,|{\makeatletter\lst@baseemflexible}|}|.
% \end{macrosyntax}
%
%
% \subsection{Listing alignment}\label{uListingAlignment}
%
% \begin{macrosyntax}
% \item[0.19,new] |indent=|\meta{dimension}
%
% indents each listing by \meta{dimension}, which is initialized with 0pt.
% This command is the best way to move line numbers (and the listing) to the right.
%
% \item[0.19,new] |wholeline=|\meta{true$\vert$false}
%
% prevents or lets the package use indention from list environments like \texttt{enumerate} or \texttt{itemize}.
%
% \item[0.16,bug,addon] |spread=|\meta{dimension}\quad or\quad|spread={|\meta{inner}|,|\meta{outer}|}|
%
% defines \emph{additional} line width for listings, which may avoid overfull |\hbox|es if a listing has long lines.
% The inner and outer spread is given explicitly or is equally shared.
% It is initialized via |spread=0pt|.
% For one sided documents 'inner' and 'outer' have the effect of 'left' and 'right'.
% Note that |\lstbox| doesn't use this spread but |indent| (which is always 'left').
%
% Bug (two sided documents):
% At top of page it's possible that the package uses inner instead of outer spread or vice versa.
% This happens when \TeX\ finally moves one or two source code lines to the next page, but hasn't decided it when the \textsf{listings} package processes them.
% Work-around: interrupt the listing and/or use an explicit |\newpage|.
%
% \item[0.17] |lineskip=|\meta{additional space between lines}
%
% specifies the additional space between lines in listings.
% You may write |lineskip=-1pt plus 1pt minus 0.5pt| for example, but 0pt is the default.
%
% \item[0.19,new] |outputpos=|\meta{c$\vert$l$\vert$r}
%
% controls horizontal orientation of smallest output units (keywords, identifiers, etc.).
% The arguments work as follows, where vertical bars visualize the effect:
% $\vert$\hbox to 4.2em{\hss l\hss i\hss s\hss t\hss i\hss n\hss g\hss }$\vert$,
% $\vert$\hbox to 4.2em{l\hss i\hss s\hss t\hss i\hss n\hss g\hss }$\vert$ and
% $\vert$\hbox to 4.2em{\hss l\hss i\hss s\hss t\hss i\hss n\hss g}$\vert$
% in fixed column mode resp.\
% $\vert$\hbox to 3.15em{\hss listing\hss}$\vert$,
% $\vert$\hbox to 3.15em{listing\hss}$\vert$ and
% $\vert$\hbox to 3.15em{\hss listing}$\vert$
% with flexible columns (using pre-defined |baseem|).
% By default the output is centered.
% To make all things clear: You may write |outputpos=c|, |outputpos=l| or |outputpos=r|.
% \end{macrosyntax}
%
%
% \subsection{Escaping to \LaTeX}
%
% \textbf{Note:} {\itshape Any escape to \LaTeX\ may disturb the column alignment since the package can't control the spacing there.}
% \begin{macrosyntax}
% \item[0.18,new] |texcl=|\meta{true$\vert$false}
%
% activates or deactivates \LaTeX\ comment lines, see the example below.
%
% \item[0.19,new] |mathescape=|\meta{true$\vert$false}
%
% activates or deactivates special behaviour of the dollar sign.
% If activated, a dollar sign acts as \TeX's text math shift (not display style!).
%
% \item[0.19,new] |escapechar=|\meta{single character} (or empty)
%
% The given character escapes the user to \LaTeX:
% All code between two such characters is interpreted as \LaTeX\ code.
% Note that \TeX's special characters must be entered with a preceding backslash, e.g.\ |escapechar=\%|.
% \end{macrosyntax}
% Some examples clarify these commands.
% Since |texcl| only makes sense with comment lines, we will use C++ comment lines here (without saying how to define them).
% Note that only the first example runs through a C++ compiler if the source code is placed in a separate file.
% All \LaTeX\ escapes are local here, but you can also use |\lstset|.
% \lstset{commentline=//}
% \begin{lstsample}{}
%\begin{lstlisting}[texcl]{}
%// calculate $a_{ij}$
% A[i][j] = A[j][j]/A[i][j];
%\end{lstlisting}
% \end{lstsample}
%
% \begin{lstsample}{}
%\begin{lstlisting}[mathescape]{}
%// calculate $a_{ij}$
% $a_{ij} = a_{jj}/a_{ij}$;
%\end{lstlisting}
% \end{lstsample}
%
% \begin{lstsample}{}
%\lstset{escapechar=\%}
%\begin{lstlisting}{}
%// calc%ulate $a_{ij}$%
% %$a_{ij} = a_{jj}/a_{ij}$%;
%\end{lstlisting}
% \end{lstsample}
% \lstset{commentline={}}
% \noindent
% In the first example the whole comment line is typset in '\LaTeX\ mode' --- except the comment line indicators |//|.
% Note that |texcl| uses comment style.
% In the second example the comment line upto $a_{ij}$ have been typeset in comment style and by the \textsf{listings} package.
% The '$a_{ij}$' itself is typeset in '\TeX\ math mode' without comment style.
% About the half comment line of the third example have been typeset by this package.
% The rest is in '\LaTeX\ mode' without comment style.
%
% To avoid problems with the current and future version of this package:
% \begin{enumerate}
% \item Don't use any command of the \textsf{listings} package when you have escaped to \LaTeX.
% \item Any environment must start and end inside the same escape.
% \item You might use |\def|, |\edef|, etc., but do not assume that the definitions are present later --- except they are |\global|.
% \item |\if \else \fi|, groups, math shifts |$| and |$$|, \ldots\ must be balanced each escape.
% \item \ldots
% \end{enumerate}
% Expand that list yourself and mail me about new items.
%
%
% \subsection{Some special keys}\label{uSomeSpecialKeys}
%
% \begin{macrosyntax}
% \item[0.18,new] |extendedchars=|\meta{true$\vert$false}
%
% allows or prohibits extended characters in listings, i.e.\ characters with codes 128--255.
% If you use extended characters, you should load the \texttt{inputenc} or \texttt{fontenc} package!
%
% \item[0.19,new,lang.spec.]|printpod=|\meta{true$\vert$false}
%
% prints or drops PODs in Perl.
%
% \item[0.12,addon] |pre=[|\meta{continue}|]{|\meta{commands to execute}|}|
% \item[0.12,addon] |post=[|\meta{continue}|]{|\meta{commands to execute}|}|
%
% The given control sequences are executed before and after typesetting resp.\ when continuing a listing, but in all cases inside a group.
% The commands are not executed if you use |\lstbox| or |\lstinline| (since the user given pre and post commands are assumed to be unsave inside |\hbox|).
% By default \meta{continue} is empty.
% The other arguments are pre-set empty.
% \end{macrosyntax}
%
% \begin{lstsample}{}
%\lstset{flexiblecolumns}
%\lstset{pre=[%
% We continue the listing.
% ]A simple prelisting example.}
%\begin{lstlisting}{}
%{ Get listings.dtx. Now! }
%\end{lstlisting}
%
%\begin{lstlisting}{ }
%{ You have it already? Good. }
%\end{lstlisting}
%
%\begin{lstlisting}{ }
%{ Tell your friends about it. }
%\end{lstlisting}
% \end{lstsample}
%\lstset{style={}}
%
%
% \subsection{Languages and styles}\label{uLanguagesAndStyles}
%
% \begin{macrosyntax}
% \item[0.17,changed] |language=[|\meta{dialect}|]|\meta{language name}
%
% activates a (dialect of a) programming language.
% All arguments are case \emph{insensitive} here.
%
% \item[0.19,new] |\lstloadlanguages{|\meta{list of languages}|}|
%
% can only be used in the preamble.
% It loads all specified languages, where each language is given in the form |[|\meta{dialect}|]|\meta{language}.
% List of languages means a comma separated list.
%
% \item[0.18,new] |style=|\meta{style name}
%
% activates a style.
% The arguments is case \emph{insensitive}.
%
% \item[0.19,new] |\lstdefinestyle{|\meta{style name}|}{|\meta{key=value list}|}|
%
% stores the key=value list: You can select the style via |style| using te style name as argument.
% \end{macrosyntax}
% After package loading a 'standard' style and an 'empty' language are active.
% The style is defined as follows.
% \begin{verbatim}
% \lstdefinestyle{}
% {basicstyle={},
% keywordstyle=\bfseries,nonkeywordstyle={},
% commentstyle=\itshape,
% stringstyle={},
% labelstyle={},labelstep=0
% }\end{verbatim}
%
%
% \subsection{Language definitions}
%
% \begin{macrosyntax}
% \item[0.19,new] |\lstdefinelanguage[|\meta{dialect}|]{|\meta{language}|}{|\meta{key=value list}|}|
%
% defines a programming language.
% Use any 'language' key=value list and the definition is yours.
%
% \item[0.19,new] |\lstdefinedrvlanguage[|\meta{dialect}|]{|\meta{language}|}{|\meta{key=value list}|}|
%
% defines a programming language only if the user has requested the language.
% Thus this command can only be used in driver files.
%
% \item[0.19,new] |defaultdialect=[|\meta{dialect}|]|\meta{language}
%
% defines a default dialect for a language, that means a dialect which is selected whenever you leave out the optional dialect.
% If you have defined a default dialect other than empty, for example |defaultdialect=[iama]fool|, you can't select the 'empty' dialect, even not with |language=[]fool|.
%
% Note that a configuration file possibly defines some default dialects.
%
% \item[0.18,new] |\lstalias{|\meta{alias}|}{|\meta{language}|}|
%
% defines an alias for a programming language.
% Any dialect of \meta{alias} selects in fact the same dialect of \meta{language}.
% It's also possible to define an alias for one dialect: |\lstalias[|\meta{dialect alias}|]{|\meta{alias}|}[|\meta{dialect}|]{|\meta{language}|}|.
% Here all four parameters are \emph{non}optional.
% An alias with empty \meta{dialect} will select the default dialect.
% Note that aliases can't be nested: The two aliases |\lstalias{foo1}{foo2}| and |\lstalias{foo2}{foo3}| redirect |foo1| not to |foo3|.
%
% Note that a configuration file possibly defines some aliases.
%
% \item[0.18,new] |\lststorekeywords|\meta{macro}|{|\meta{keywords}|}|
%
% stores \meta{keywords} in \meta{macro} for use with keyword keys.
% This command can't be used in a language definition since it is a command and not a key.
% \end{macrosyntax}
%
% Now come all the language keys, which might be used in the key=value list of |\lstdefinelanguage|.
% Note: {\itshape If you want to enter {\upshape|\|, |{|, |}|, |%|, |#|} or {\upshape|&|} inside or as an argument here, you must do it with a preceding backslash!}
%
% \begin{macrosyntax}
% \item[0.11] |keywords={|\meta{keywords}|}|
% \item[0.11] |morekeywords={|\meta{additional keywords}|}|
% \item[0.18,new] |deletekeywords={|\meta{keywords to remove}|}|
%
% \item[0.19,new,optional] |ndkeywords={|\meta{second keywords}|}|
% \item[0.19,new,optional] |morendkeywords={|\meta{additional second keywords}|}|
% \item[0.19,new,optional] |deletendkeywords={|\meta{second keywords to remove}|}|
%
% \item[0.19,new,optional] |rdkeywords={|\meta{third keywords}|}|
% \item[0.19,new,optional] |morerdkeywords={|\meta{additional third keywords}|}|
% \item[0.19,new,optional] |deleterdkeywords={|\meta{third keywords to remove}|}|
%
% Each 'keyword' argument (here and below) is a list of keywords separated by commas.
% You might use macros defined with |\lststorekeywords| as elements (i.e.\ also separated by commas).
% |keywords={save,Test,test}| defines three keywords (if keywords are case sensitive).
% If you want to remove them all, simply write |keywords={}| --- in |\lstset|'s argument, in an optional argument or in a language definition.
% The characters |\|, |{|, and |}| (entered as |\\|, |\{| and |\}|) are \emph{not} allowed within a keyword.
% You might use each of
%^^A
%^^A We need some definitions here.
%^^A
%\makeatletter ^^A
%\def\lstspec#1{^^A
% \ifx\relax#1\else ^^A
% {\lstset{keywords=#1}\setbox\@tempboxa\hbox{\lstinline a#1a}}^^A
% \lst@ifspec\lstinline a#1a\fi ^^A
% \expandafter\lstspec ^^A
% \fi}^^A
%\lst@AddToHook{Output}{\lstspectest}^^A
%\gdef\lstspecfalse{\global\let\lst@ifspec\iffalse}^^A
%\gdef\lstspectest{^^A
% \global\let\lst@ifspec=\iftrue ^^A
% \ifx\lst@thestyle\lst@keywordstyle\else ^^A
% \lstspecfalse ^^A
% \fi}^^A
%\makeatother ^^A
% {\lstset{language={}}^^A
% \lstspec !"\#$\%\&'()*+-./:;<=>?[]^`\relax.}
%^^A
%^^A a comma also works!
%^^A
%^^A End of test.
%^^A
% But note that you must enter |\#|, |\%| and |\&| instead of |#|, |%| and |&|.
%
% \item[0.14] |sensitive=|\meta{true$\vert$false}
%
% makes the keywords (first, second and third) case sensitive resp.\ insensitive.
%^^A It would be nice to have |\lst|\meta{\texttt{nd}$\vert$\texttt{rd}}|sensitive|\meta{\texttt{true}\textbar\texttt{false}}?
% This key affect the keywords only in the phase of typesetting.
% In all other situations keywords are case sensitive, i.e.\ |deletekeywords={save,Test}| removes 'save' and 'Test', but neither 'SavE' nor 'test'.
%
% \item[0.19,new] |alsoletters={|\meta{character sequence}|}|
% \item[0.19,new] |alsodigits={|\meta{character sequence}|}|
% \item[0.19,new] |alsoother={|\meta{character sequence}|}|
%
% These keys support the 'special character' auto-detection of the keyword commands.
% For our purpose here, identifiers are out of letters (|A|--|Z|,|a|--|z|,|_|,|@|,|$|) and digits (|0|--|9|), but an identifier must begin with a letter.
% If you write |keywords={one-two,\#include}|, the minus becomes necessarily a digit and the sharp a letter since the keywords can't be detected otherwise.
% The three keys overwrite such default behaviour.
% Each character of the sequence becomes a letter, digit and other, respectively.
% Note that the auto-detection might fail if you remove keywords and always fails if you use special characters not listed above.
%^^A
%^^A TODO: This is mainly due to improper \lst@ReplaceIn inside ..MakeKeywordArg..
%^^A
%
% \item[0.19,new] |stringtest=|\meta{true$\vert$false}
%
% enables or disables string tests:
% If activated, line exceeding strings issue warnings and the package exits string mode.
%
% \item[0.12,addon] |stringizer=[|\meta{b$\vert$d$\vert$m$\vert$bd}|]{|\meta{character sequence}|}|
%
% Each character might start a string or character literal.
% 'Stringizers' match each other, i.e.\ starting and ending delimiters are the same.
% The optional argument controls how the stringzier(s) itself is/are represented in a string or character literal:
% It is preceded by a |b|ackslash, |d|oubled (or both is allowed via |bd|) or it is |m|atlabed.
% The latter one is a special type for Ada and Matlab and possibly more languages, where the stringizers are also used for other purposes.
% In general the stringizer is also doubled, but a string does not start after a letter or a right parenthesis.
%
% \item[0.19,new,lang.spec.] |texcs={|\meta{list of control sequences \textup(without backslashes\textup)}|}|
%
% defines control sequences for \TeX\ and \LaTeX.
%
% \item[0.18,new,lang.spec.] |cdirectives={|\meta{list of compiler directives}|}|
%
% defines compiler directives in C, C++ and Objective-C.
% \end{macrosyntax}
% If you have already defined any of the following comments and you want to remove it, let all arguments to the comment key empty.
% \begin{macrosyntax}
% \item[0.13,changed] |commentline=|\meta{1or2 chars}
%
% The characters (\emph{in the given order}) start a comment line, which in general starts with the comment separator and ends at end of line.
% If the character sequence |//| starts a comment line (like in C++, Comal 80 or Java), |commentline=//| is the correct declaration.
% For Matlab it would be |commentline=\%| --- note the preceding backslash.
%
% \item[0.18,new] |fixedcommentline=[|\meta{n=preceding columns}|]{|\meta{character sequence}|}|
%
% Each given character becomes a 'fixed comment line' separator: It starts a comment line if and only if it is in column $n+1$.
% Fortran 77 declares its comments via |fixedcommentline={*Cc}| ($n=0$ is default).
%
% \item[0.13,changed] |singlecomment={|\meta{1or2 chars}|}{|\meta{1or2 chars}|}|
% \item[0.13,changed] |doublecomment={|\meta{1or2 chars}|}{|\meta{1or2 chars}|}{|\meta{1or2 chars}|}{|\meta{1or2 chars}|}|
%
% Here we have two or four comment separators.
% The first starts and the second ends a comment, and similarly the third and fourth separator for double comments.
% If you need three such comments use |singlecomment| and |doublecomment| at the same time.
% C, Java, PL/I, Prolog and SQL all define single comments via |singlecomment={/*}{*/}|, and Algol does it with |singlecomment={\#}{\#}|, which means that the sharp delimits both beginning and end of a single comment.
%
% \item[0.13,changed] |nestedcomment={|\meta{1or2 chars}|}{|\meta{1or2 chars}|}|
%
% is similar to |singlecomment|, but comments can be nested.
% Identical arguments are not allowed --- think a while about it!
% Modula-2 and Oberon-2 use |nestedcomment={(*}{*)}|.
%
% \item[0.17,lang.spec.] |keywordcomment={|\meta{keywords}|}|
% \item[0.17,lang.spec.] |doublekeywordcommentsemicolon={|\meta{keywords}|}{|\meta{keywords}|}{|\meta{keywords}|}|
%
% A (paired) keyword comment begins with a keyword and ends with the same keyword.
% Consider |keywordcomment={comment,co}|.
% Then '\textbf{comment}\allowbreak\ldots\textbf{comment}' and '\textbf{co}\ldots\textbf{co}' are comments.\\
%^^A
% Defining a double keyword comment (semicolon) needs three keyword lists, e.g.\ |{end}{else,end}{comment}|.
% A semicolon always ends such a comment.
% Any keyword of the first argument begins a comment and any keyword of the second argument ends it (and a semicolon also); a comment starting with any keyword of the third argument is terminated with the next semicolon only.
% In the example all possible comments are '\textbf{end}\ldots\textbf{else}', '\textbf{end}\ldots\textbf{end}' (does not start a comment again) and '\textbf{comment}\ldots;' and '\textbf{end}\ldots;'.
% Maybe a curious definition, but Algol and Simula use such comments.\\
%^^A
% Note: The keywords here need not to be a subset of the defined keywords.
% They won't appear in keyword style if they aren't.
% \end{macrosyntax}
%
%
% \section{Experimental features}
%
% This section describes the more or less unestablished parts of the \textsf{listings} package.
% It's unlikely that they are removed, but they are liable to (heavy) changes and maybe improvements.
%
%
% \subsection{Interface to \textsf{fancyvrb}}
%
% The \textsf{fancyvrb} package --- fancy verbatims --- from Timothy van Zandt provides macros for reading, writing and typesetting verbatim code.
% It has some remarkable features the \textsf{listings} package doesn't have --- some are also possible with \textsf{listings}, but you must find somebody who implements them ; -- ).
% The \textsf{fancyvrb} package is available from \texttt{CTAN: macros/latex/contrib/supported/fancyvrb}.
%
% \begin{macrosyntax}
% \item [0.19,new]|fancyvrb=|\meta{true$\vert$false}
%
% activates or deactivates the interface.
% This defines an appropiate version of |\FancyVerbFormatLine| to make the two packages work together.
% If active, the verbatim code read by the \textsf{fancyvrb} package is typeset by the \textsf{listings} package, i.e.\ with emphasized keywords, strings, comments, and so on.
% --- You should know that |\FancyVerbFormatLine| is responsible for the typesetting a single code line.
%
% If \textsf{fancyvrb} and \textsf{listings} provide similar functionality, use \textsf{fancyvrb}'s.
%
% Note that this is the first interface.
% It works only with |Verbatim|, neither with |BVerbatim| nor |LVerbatim|.
% And you shouldn't use \textsf{defineactive}. (As I can see it doesn't matter since it does nothing at all.)
% I hope to remove some restrictions in future.
% \end{macrosyntax}
%
% \iffancyvrb
% \begin{lstsample}{}
%\lstset{commentline=\ }% :-)
%
%\begin{Verbatim}[commandchars=\\\{\}]
%First verbatim line.
%\fbox{Second} verbatim line.
%\end{Verbatim}
%
%\lstset{fancyvrb}
%\begin{Verbatim}[commandchars=\\\{\}]
%First verbatim line.
%\fbox{Second} verbatim line.
%\end{Verbatim}
%\lstset{fancyvrb=false}
% \end{lstsample}
% \noindent
% The last two lines are wider than the first two since |baseem| equals not the width of a single typewriter character.
% \else
% \begin{center}
% \textsf{fancyvrb} seems to be unavailable on your platform, thus the example couldn't be printed here.
% \end{center}
% \fi
%
%
% \subsection{Listings inside arguments}\label{uListingsInsideArguments}
%
% There are some things to consider if you want to use |\lstinline| or the listing environment inside arguments.
% Since \TeX\ reads the argument before the '\lst-macro' is executed, this package can't do anything to preserve the input:
% Spaces shrink to one space, the tabulator and the end of line are converted to spaces, the comment character is not printable, and so on.
% Hence, you must work a little bit more.
% You have to put a backslash in front of each of the following four characters: |\{}%|.
% Moreover you must protect spaces in the same manner if: (i) there are two or more spaces following each other or (ii) the space is the first character in the line.
% That's not enough: Each line must be terminated with a 'line feed' |^^J|.
% Finally you can't escape to \LaTeX\ inside such listings.
%
% The easiest examples are with |\lstinline| since we need no line feed.
% \begin{verbatim}
%\footnote{\lstinline!var i:integer;! and
% \lstinline!protected\ \ spaces! and
% \fbox{\lstinline!\\\{\}\%!}}\end{verbatim}
% yields\lstset{language=Pascal}\footnote{\lstinline!var i:integer;! and \lstinline!protected\ \ spaces! and \fbox{\lstinline!\\\{\}\%!}} if the current language is Pascal.
% The environment possibly needs a preceding |\lstbox|, as the following examples show.
%
%{\let\smallbreak\relax\lstset{language={}}
% \begin{lstsample}{}
%\fbox{\lstbox
%\begin{lstlisting}{}^^J
%\ !"#$\%&'()*+,-./^^J
%0123456789:;<=>?^^J
%@ABCDEFGHIJKLMNO^^J
%PQRSTUVWXYZ[\\]^_^^J
%`abcdefghijklmno^^J
%pqrstuvwxyz\{|\}~^^J
%\end{lstlisting}}
% \end{lstsample}
%
% \lstset{language={}}
% \begin{lstsample}{}
%\fbox{\lstbox
%\begin{lstlisting}{}^^J
%We need no protection here,^^J
%\ but\ \ in\ \ this\ \ line.^^J
%\end{lstlisting}}
% \end{lstsample}
%}
%
%
% \subsection{Frames}
%
% \begin{macrosyntax}
% \item [0.19,new] |frame=|\meta{any subset of \textup{\texttt{tlrbTLRB}}}
%
% The characters |tlrbTLRB| are attached to lines at the |t|op of a listing, on the |l|eft, |r|ight and at the |b|ottom.
% There are two lines if you use upper case letters.
% If you want a single frame around a listing, write |frame=tlrb| or |frame=bltr| for example (but as optional argument or argument to |\lstset|, of course).
% If you want double lines at the top and on the left and no other lines, write |frame=TL|.
% Note that frames reside outside the listing's space.
% Use |spread| if you want to shrink frames (to |\linewidth| for example) and use |indent| if you want to move line number inside frames.
%
% \item [0.19,new] |framerulewidth=|\meta{dimension}
% \item [0.19,new] |framerulesep=|\meta{dimension}
%
% These keys control the width of the rules and the space between double rules.
% The predefined values are {\makeatletter\lst@framewidth} width and {\makeatletter\lst@framesep} separation.
%
%\iffalse
% \item [0.19,new] |frametextsep=|\meta{dimension}
%
% controls the space between frame and listing, but currently only between the listing and vertical frame lines.
% The predefined value is {\makeatletter\lst@frametextsep}.
%\fi
% \end{macrosyntax}
% |frame| does not work with |\lstbox| or |fancyvrb=true|!
% And there are certainly more problems with other commands.
% Take the time to report in.
%
% \begin{lstsample}{}
%\begin{lstlisting}[frame=tLBr]{}
%for i:=maxint to 0 do
%begin
% { do nothing }
%end;
%\end{lstlisting}
% \end{lstsample}
%
%
% \subsection{Export of identifiers}
%
%^^A \lsthelper{Aslak Raanes}{araanes@ifi.ntnu.no}{1997/11/24}{export function names}
% It would be nice to export function or procedure names, for example to index them automatically or to use them in |\listoflistings| instead of a listing name.
% In general that's a dream so far.
% The problem is that programming languages use various syntaxes for function and procedure declaration or definition.
% A general interface is completely out of the scope of this package --- that's the work of a compiler and not of a pretty printing tool.
% However, it is possible for particular languages: in Pascal each function or procedure definition and variable declaration is preceded by a particular keyword.
% \begin{macrosyntax}
% \item [0.19,new,optional] |index={|\meta{identifiers}|}|
%
% \meta{identifiers} is a comma-separated list of identifiers.
% Each appearance of such an identifier is indexed.
%
% \item [0.19,new,optional] |indexmacro=|\meta{'one parameter' macro}
%
% The specified macro gets exactly one parameter, namely the identifier, and must do the indexing.
% It is predefined as |indexmacro=\lstindexmacro|, which definition is
% \begin{verbatim}
% \newcommand\lstindexmacro[1]{\index{{\ttfamily#1}}}\end{verbatim}
% \item[0.19,new,optional] |prockeywords={|\meta{keywords}|}|
%
% \meta{keywords} is a comma-separated list of keywords, which indicate a function or procedure definition.
% Any identifier following such a keyword appears in 'procname' style.
% For Pascal you might use
% \begin{verbatim}
% prockeywords={program,procedure,function}\end{verbatim}
%
% \item[0.19,new,optional] |procnamestyle=|\meta{style for procedure names}
%
% defines the style in which procedure and function names appear.
%
% \item[0.19,new,optional] |indexprocnames=|\meta{true$\vert$false}
%
% If activated, procedure and function names are also indexed (if used with |index| option).
% \end{macrosyntax}
%
%
% \section{Troubleshooting}
%
% The known bugs have already been described.
% This section deals with problems concerning not only the \textsf{listings} package.
%
%
% \subsection{Problems with \texttt{.fd} files}
%
% You probably get the following error message with a different font definition file:
% \begin{verbatim}
%! LaTeX Error: Command textparagraph unavailable in encoding T1.
%
%See the LaTeX manual or LaTeX Companion for explanation.
%Type H <return> for immediate help.
% ...
%
%l.68 \P
% rovidesFile{omscmr.fd}
%?\end{verbatim}
% So, what happened?
% (a) The \textsf{listings} package redefines the character table to print listings.
% (b) \LaTeX\ loads the font definition files on demand.
% (a) plus (b) gives the error: \LaTeX\ loads the \texttt{.fd} files with modified character table.
% And that goes wrong.
% The work-around is quite easy: Input the \texttt{.fd} file before typesetting the listing.
%
%
% \subsection{Language definitions}
%
% Language definitions and also some style definitions tend to have long definition parts.
% This is why we tend to forget commas between the key=value elements.
% If you select a language and get a |Missing = inserted for \ifnum| error, this is surely due to a missing comma after |keywords=|value.
% If you encounter unexspected characters after selecting a language (or style), you have either forgotten a comma or you have given to many arguments to a key, for example |commentline={--}{!}|.
%
%
% \section{Forthcoming}
%
% \begin{itemize}
% \item I'd like to support more languages, for example Maple, Mathematica, PostScript, Reduce and so on.
% Fortunately my lifetime is limited, so other people may do that work.
% Write a language definition and (e-)mail it to me (with a proposal in which file to place the definition).
%
% \item There will possibly a boolean |blanklisting=|\meta{true$\vert$false} or a $*$-version of the environment.
%
% \item 'procnames' is already interesting, but marks (and indexes) only the function definitions so far.
% It would be quite easy to mark also the following function calls:
% Write another 'keyword class' which is empty at the very beginning (and can be reset with a key); each function definition appends a 'keyword' which will appear in 'procnamestyle'.
% But this would be another 'keyword test' within an inner loop.
% \item I plan to put all language definitions in a single file.
% \end{itemize}
%
%
% \StopEventually{}
%
%
% \part{Implementation}
%
% \CheckSum{5520}
% \DoNotIndex{\[,\{,\},\],\1,\2,\3,\4,\5,\6,\7,\8,\9,\0}
% \DoNotIndex{\`,\,,\!,\#,\$,\&,\',\(,\),\+,\.,\:,\;,\<,\=,\>,\?,\_}
% \DoNotIndex{\@@end,\@@par,\@currenvir,\@depth,\@dottedtocline,\@ehc}
% \DoNotIndex{\@empty,\@firstoftwo,\@gobble,\@gobbletwo,\@gobblefour,\@height}
% \DoNotIndex{\@ifnextchar,\@ifundefined,\@namedef,\@ne,\@secondoftwo}
% \DoNotIndex{\@spaces,\@starttoc,\@undefined,\@whilenum,\@width}
% \DoNotIndex{\A,\active,\addtocontents,\advance,\aftergroup,\batchmode}
% \DoNotIndex{\begin,\begingroup,\bfseries,\bgroup,\box,\bigbreak,\bullet}
% \DoNotIndex{\c@page,\catcode,\contentsname,\csname,\def,\divide,\do,\dp}
% \DoNotIndex{\edef,\egroup,\else,\end,\endcsname,\endgroup,\endinput}
% \DoNotIndex{\endlinechar,\escapechar,\everypar,\expandafter,\f@family}
% \DoNotIndex{\fi,\footnotesize,\gdef,\global,\hbox,\hss,\ht}
% \DoNotIndex{\if,\ifdim,\iffalse,\ifnum,\ifodd,\iftrue,\ifx}
% \DoNotIndex{\ignorespaces,\index,\input,\itshape,\kern}
% \DoNotIndex{\lccode,\l@ngrel@x,\leftskip,\let,\linewidth,\llap}
% \DoNotIndex{\long,\lowercase,\m@ne,\makeatletter,\mathchardef}
% \DoNotIndex{\message,\multiply,\NeedsTeXFormat,\newbox,\new@command}
% \DoNotIndex{\newcommand,\newcount,\newdimen,\newtoks,\noexpand}
% \DoNotIndex{\noindent,\normalbaselines,\normalbaselineskip}
% \DoNotIndex{\offinterlineskip,\par,\parfillskip,\parshape}
% \DoNotIndex{\parskip,\ProcessOptions,\protect,\ProvidesPackage}
% \DoNotIndex{\read,\relax,\removelastskip,\rightskip,\rlap,\setbox}
% \DoNotIndex{\smallbreak,\smash,\space,\string,\strut,\strutbox}
% \DoNotIndex{\the,\thepage,\ttdefault,\ttfamily,\tw@,\typeout,\uppercase}
% \DoNotIndex{\vbox,\vcenter,\vrule,\vtop,\wd,\xdef,\z@,\zap@space}
% \DoNotIndex{\char,\closeout,\immediate,\newwrite,\openout,\write}
% \DoNotIndex{\vskip}
%
% \DoNotIndex{\define@key,\setkeys}
%
% \DoNotIndex{\textasciicircum,\textasciitilde,\textasteriskcentered}
% \DoNotIndex{\textbackslash,\textbar,\textbraceleft,\textbraceright}
% \DoNotIndex{\textdollar,\textendash,\textgreater,\textless}
% \DoNotIndex{\textunderscore,\textvisiblespace}
%
% \DoNotIndex{\filename@area,\filename@base,\filename@ext}
% \DoNotIndex{\filename@parse,\IfFileExists,\InputIfFileExists}
% \DoNotIndex{\DeclareOption,\MessageBreak}
% \DoNotIndex{\GenericError,\GenericInfo,\GenericWarning}
%
% \DoNotIndex{\blankstringfalse,\blankstringtrue,\commentstyle}
% \DoNotIndex{\DeclareCommentLine,\DeclareDoubleComment}
% \DoNotIndex{\DeclareNestedComment,\DeclarePairedComment}
% \DoNotIndex{\DeclareSingleComment,\inputlisting,\inputlisting@,\keywords}
% \DoNotIndex{\keywordstyle,\labelstyle,\listingfalse,\listingtrue}
% \DoNotIndex{\morekeywords,\normallisting,\postlisting,\prelisting}
% \DoNotIndex{\selectlisting,\sensitivefalse,\sensitivetrue}
% \DoNotIndex{\spreadlisting,\stringizer,\stringstyle,\tablength}
%
% \DoNotIndex{\lst@AddToHook@,\lst@Aspect@,\is,\lst@AspectGobble}
% \DoNotIndex{\lst@DeleteKeysIn@,\lst@Environment@}
% \DoNotIndex{\lst@IfNextChars@,\lst@IfNextChars@@,\lst@KCOutput@}
% \DoNotIndex{\lst@MakeActive@,\lst@MSkipUptoFirst@,\lst@ReplaceIn@}
% \DoNotIndex{\lst@LocateLanguage@,\lst@SKS@,\lstalias@,\lstalias@@}
% \DoNotIndex{\lstbaseem@,\lstbox@,\lstCC@ECUse@,\lstCC@Escape@}
% \DoNotIndex{\lstCC@CBC@,\lstCC@CBC@@,\lstCC@CommentLine@}
% \DoNotIndex{\lstCC@EndKeywordComment@,\lstCC@FixedCL@}
% \DoNotIndex{\lstCC@ProcessEndPOD@,\lstCC@SpecialUseAfter@}
% \DoNotIndex{\lstCC@Stringizer@,\lstdrvlanguage@,\lstenv@AddArg@}
% \DoNotIndex{\lstenv@Process@,\lstenv@ProcessJ@,\lstinputlisting@}
% \DoNotIndex{\lstoutputpos@,\lstresetlineno@,\lstresetlineno@@}
% \DoNotIndex{\lstspread@}
% \DoNotIndex{\lstnestedcomment@,\lstpost@,\lstpre@,\lststringizer@}
%
%
% \section{Overture}
%
% The version 0.19 kernel needs 1 token register, 6 counters and 5 dimensions.
% The macros, boxes and counters |\@temp?a| and |\@temp?b| and the dimension |\@tempdima| are also used, see the index.
% And I shouldn't forget |\@gtempa|.
% Furthermore, the required \textsf{keyval} package allocates one token register.
% The \textsf{fancyvrb} interface needs one box.
%
% Before considering the implementation, here some conventions I used:
% \begin{itemize}
% \item All public macros have lower case letters and the prefix \lst.
% \item The name of all private macros and variables use the prefixes (possibly not up to date):
% \begin{itemize}
% \item |lst@| for a general macro or variable,
% \item |lstenv@| if it is defined for the listing |env|ironment,
% \item |lstCC@| for |c|haracter |c|lass macros,
% \item |lsts@| for |s|aved character meanings,
% \item |lstf@| for frame declaration,
% \item |\lsthk@|\meta{name of hook} holds hook material,
% \item a language may define (|Pre| for prepare, |SCT| for select char table)
% \begin{itemize}
% \item[] |\lstPre@|\meta{language}
% \item[] |\lstPre@|\meta{language}|@|\meta{dialect}
% \item[] |\lstSCT@|\meta{language}
% \item[] |\lstSCT@|\meta{language}|@|\meta{dialect}
% \end{itemize}
% where the first two are executed (if they exist) one time each listing (before selecting character table, but after executing the hook Before\-Select\-Char\-Table).
% The other two macros are called possibly more than once, namely whenever the package selects the character table.
% The specialized \meta{dialect} versions are called after the more general \meta{language} macros.
% \item |lstk@| is reserved for keyword tests,
%
% \item |\lstlang@|\meta{language}|@|\meta{dialect} contains a language definition,
% \item |\lststy@|\meta{the style} contains style definition,
%
% \item |\lstloc@|\meta{language} keeps location (= file name without extension) of a language definition if it's not |lst|\meta{language},
% \item |\lsta@|\meta{language}|@|\meta{dialect} contains alias,
% \item |\lstaa@|\meta{language} contains alias for all dialects of a language,
% \item |\lstdd@|\meta{language} contains default dialect of a language (if present).
% \end{itemize}
% \item If a submacro does the main work, e.g.\ |\lstinputlisting@| does it for |\lstinputlisting|, we use the suffix |@|.
% \item To distinguish procedure-like macros from macros holding data, the name of procedure macros use upper case letters with each beginning word, e.g.\ |\lst@AddTo|.
% \end{itemize}
%
% The kernel starts with identification and option declaration and processing.
% \begingroup
% \begin{macrocode}
%<*kernel>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{listings}[1998/11/09 v0.19 by Carsten Heinz]
\RequirePackage{keyval}
% \end{macrocode}
% \begin{macrocode}
\DeclareOption{0.17}{\@namedef{lst@0.17}{}}
\DeclareOption{index}{\@namedef{lst@index}{}}
\DeclareOption{procnames}{\@namedef{lst@prockeywords}{}}
\DeclareOption{ndkeywords}{\@namedef{lst@ndkeywords}{}}
\DeclareOption{rdkeywords}{\@namedef{lst@rdkeywords}{}}
\DeclareOption{doc}{\@namedef{lst@doc}{}}
\ProcessOptions
%</kernel>
% \end{macrocode}
% Note that |doc| option is designed for this documentation only.
% \endgroup
%
% \begingroup
% \begin{macrocode}
%<*info>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@InfoInfo}
% \begin{macro}{\lst@InfoWarning}
% \begin{macro}{\lst@InfoError}
% Each macro gets one argument, which is printed (\texttt{.log} and/or screen) as info, warning or error.
% \begin{macrocode}
\def\lst@InfoInfo#1{%
\GenericInfo %
{(Listings) \@spaces\@spaces\space\space}%
{Listings Info: #1}}
% \end{macrocode}
% \begin{macrocode}
\def\lst@InfoWarning#1{%
\GenericWarning %
{(Listings) \@spaces\@spaces\@spaces\space}%
{Listings Warning: #1}}
% \end{macrocode}
% \begin{macrocode}
\def\lst@InfoError#1{%
\GenericError %
{(Listings) \@spaces\@spaces\@spaces\space}%
{Listings Error: #1}%
{See the package documentation for explanation.}%
{You're using a debug version of listings.sty.^^J%
Contact your system administrator to install nondebug one.}}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}
% \begingroup
% \begin{macrocode}
%</info>
% \end{macrocode}
% \endgroup
%
%
% \section{General problems and \TeX{}niques}
%
%
% \subsection{Quick 'if parameter empty'}
%
% There are many situations where you have to look whether or not a macro parameter is empty.
% Let's say, we want to test |#1|.
% The \emph{natural} way would be something like
% \begin{verbatim}
% \def\test{#1}%
% \ifx \test\empty %
% % #1 is empty
% \else %
% % #1 is not empty
% \fi %\end{verbatim}
% where |\empty| is defined by |\def\empty{}|, of course.
% And now the \emph{mad} way:
% \begin{verbatim}
% \ifx \empty#1\empty %
% % #1 is empty
% \else %
% % #1 is not empty
% \fi %\end{verbatim}
% If the parameter is empty, the |\empty| left from |#1| is compared with the |\empty| on the right.
% All is fine since they are the same.
% If the parameter is not empty, the |\empty| on the left is compared with the first token of the parameter.
% Assuming this token is not equivalent to |\empty| the |\else| section is executed, as desired.
%
% The mad way works if and only if the first token of the parameter is not equivalent to |\empty|.
% You must check if this meets your purpose.
% The two |\empty|s might be replaced by any other macro, which is not equivalent to the first token of the parameter.
% But the definition of that macro shouldn't be too complex since this would slow down the |\ifx|.
% In the examples above the mad version needs about $45\%$ of the natural's time.
% Note that this \TeX{}nique lost its importance from version 0.18 on.
%
%
% \subsection{Replacing characters}\label{iReplacingCharacters}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% In this section we define the macro
% \begin{macrosyntax}
% \item |\lst@ReplaceIn|\meta{macro}|{|\meta{replacement list $c_1m_1$\ldots$c_nm_n$}|}|
% \end{macrosyntax}
% Each character $c_i$ inside the given macro is replaced by the macro $m_i$.
% In fact, $c_i$ may be a character sequence (enclosed in braces and possibly containing macros), but $m_i$ must be a single macro which is not equivalent to |\empty| --- use |\relax| instead.
% |\lst@ReplaceIn\lst@arg{_\textunderscore {--}\textendash}| is allowed but not |\lst@ReplaceIn\lst@arg{\textunderscore_\textendash{--}}|.
% These restrictions can be dropped, see the TODO part below.
%
% We derive the main macro from \LaTeX's |\zap@space|:
% \begin{verbatim}
% \def\zap@space#1 #2{%
% #1%
% \ifx#2\@empty\else\expandafter\zap@space\fi
% #2}\end{verbatim}
% It is called like this:
% \begin{verbatim}
% \zap@space Some characters with(out) sense and \@empty
% \expandafter\zap@space\lst@arg{} \@empty
% \edef\lst@arg{\expandafter\zap@space\lst@arg{} \@empty}\end{verbatim}
% Note that |{}|\textvisiblespace\ produces a space holding up the syntax of |\zap@space|: it's defined with a space between the two parameters.
% If we want to replace a space by a visible space, we could use
% \begin{verbatim}
% \def\lst@temp#1 #2{%
% #1%
% \ifx#2\@empty\else %
% \noexpand\textvisiblespace %
% \expandafter\lst@temp %
% \fi #2}\end{verbatim}
% The additional |\noexpand\textvisiblespace| inserts visible spaces where spaces have been.
% We want to replace several characters and thus have to save our intermediate results.
% So we will follow the third '|\edef|' example.
% But there is some danger: After replacing the first character, the macro $m_1$ will expand inside the next |\edef|.
% Knowing that letters don't expand, we simply say that $m_1$ is a letter.
% Such changes must be local, so \ldots
%
% \begin{macro}{\lst@ReplaceIn}
% we open a group, store the original macro contents in |\@gtempa| and start a loop.
% Afterwards we close the group and assign the modified character string to our given macro.
% \begin{macrocode}
\def\lst@ReplaceIn#1#2{%
\bgroup \global\let\@gtempa#1%
\lst@ReplaceIn@#2\@empty\@empty %
\egroup \let#1\@gtempa}
% \end{macrocode}
% If we haven't reached the end of the list (the two |\@empty|s), we let the macro $m_i$ be a letter and define an appropiate macro to replace the character (sequence) |#2| by the macro |#3|.
% \begin{macrocode}
\def\lst@ReplaceIn@#1#2{%
\ifx\@empty#2\else %
\let#2=a%
\def\lst@temp##1#1##2{##1%
\ifx\@empty##2\else %
#2\expandafter\lst@temp %
\fi ##2}%
% \end{macrocode}
% Now we call that macro using |\xdef| (since the changes in |\@gtempa| must exist after closing a group).
% Finally we continue the loop.
% \begin{macrocode}
\xdef\@gtempa{\expandafter\lst@temp\@gtempa#1\@empty}%
\expandafter\lst@ReplaceIn@ %
\fi}
% \end{macrocode}
% \begin{TODO}
% This |\lst@ReplaceIn| is currently sufficient.
% If we need to replace character sequences by character sequences (instead of single macros), we have to make some minor changes.
% The main difference is that we build the new contents inside |\lst@temp| instead of using |\edef|.
% Note that the improved version is much slower than the macros above.\vspace*{-\baselineskip}
% \begin{verbatim}
%\def\lst@ReplaceIn#1#2{\lst@ReplaceIn@#1#2\@empty\@empty}
%\def\lst@ReplaceIn@#1#2#3{%
% \ifx\@empty#3\else %
% \def\lst@temp##1#2##2{%
% \ifx\@empty##2%
% \lst@lAddTo#1{##1}%
% \else %
% \lst@lAddTo#1{##1#3}%
% \expandafter\lst@temp %
% \fi ##2}%
% \let\@tempa#1\let#1\@empty %
% \expandafter\lst@temp\@tempa#2\@empty %
% \expandafter\lst@ReplaceIn@\expandafter#1%
% \fi}\end{verbatim}
% \removelastskip
% Even here you will have a problem replacing a single brace, if it has the meaning of opening or closing a group:
% You can't enter it as an argument!
% \end{TODO}
% \end{macro}
%
% \begin{macro}{\lst@DeleteKeysIn}
% We define another macro, which looks quite similar to |\lst@ReplaceIn|.
% The arguments are two macros containing a comma separated keyword list.
% All keywords in the second list are removed from the first.
% \begin{macrocode}
\def\lst@DeleteKeysIn#1#2{%
\bgroup \global\let\@gtempa#1%
\let\lst@dollar=A\let\lst@minus=B\let\lst@underscore=C%
\expandafter\lst@DeleteKeysIn@#2,\relax,%
\egroup \let#1\@gtempa}
% \end{macrocode}
% To terminate the loop we remove the very last |\lst@DeleteKeysIn@| with |\@gobble|.
% \begin{macrocode}
\def\lst@DeleteKeysIn@#1,{%
\ifx\relax#1\@empty %
\expandafter\@gobble %
\else %
\ifx\@empty#1\@empty\else %
\def\lst@temp##1,#1##2{##1\ifx\@empty##2\else %
\ifx,##2\else #1\fi \expandafter\lst@temp\fi ##2}%
\xdef\@gtempa{%
\expandafter\lst@temp\expandafter,\@gtempa,#1\@empty}%
\fi %
\fi %
\lst@DeleteKeysIn@}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Looking ahead for character sequences}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@IfNextChars}
% The macro |\@ifnextchar|\meta{single character}|{|\meta{then part}|}{|\meta{else part}|}| from the \LaTeX{} kernel is well known:
% Whether or not the character behind the three arguments --- usually a character from the 'user input stream' --- equals the given single character the 'then' or 'else' part is executed.
% We define a macro which looks for an arbitrary character sequence stored in a macro:{}
% \begin{macrosyntax}
% \item |\lst@IfNextChars|\meta{macro}|{|\meta{then part}|}{|\meta{else part}|}|
% \end{macrosyntax}
% Note an important difference:
% \LaTeX's |\@ifnextchar| doesn't remove the character behind the arguments, but we remove the characters until it is possible to decide whether the 'then' or 'else' part must be executed.
% However, we save these characters in a macro called |\lst@eaten|, so they can be inserted if necessary.
%
% We save the arguments and call the macro which does the comparisons.
% \begin{macrocode}
\def\lst@IfNextChars#1#2#3{%
\let\lst@tofind#1\def\@tempa{#2}\def\@tempb{#3}%
\let\lst@eaten\@empty \lst@IfNextChars@}
% \end{macrocode}
% This macro reads the next character from the input and compares it with the next character from |\lst@tofind|.
% We append |#1| to the eaten characters and get the character we are looking for (via |\lst@IfNextChars@@|).
% \begin{macrocode}
\def\lst@IfNextChars@#1{%
\lst@lAddTo\lst@eaten{#1}%
\expandafter\lst@IfNextChars@@\lst@tofind\relax %
\ifx #1\lst@temp %
% \end{macrocode}
% If the characters are the same, we either execute |\@tempa| or continue the test.
% \begin{macrocode}
\ifx\lst@tofind\@empty %
\let\lst@next\@tempa %
\else %
\let\lst@next\lst@IfNextChars@ %
\fi %
\expandafter\lst@next %
\else %
% \end{macrocode}
% If the characters are different, we have to call |\@tempb|.
% \begin{macrocode}
\expandafter\@tempb %
\fi}
% \end{macrocode}
% Finally comes the subsubmacro |\lst@IfNextChars@@| used above, which assigns the next character to |\lst@temp| and the rest upto |\relax| to |\lst@tofind|.
% If the implementation is not clear, read the last sentence again.
% \begin{macrocode}
\def\lst@IfNextChars@@#1#2\relax{\let\lst@temp#1\def\lst@tofind{#2}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@IfNextCharsArg}
% The difference between |\lst@IfNextChars| and the macro here is that the first parameter is a character sequence and not a macro.
% Moreover, the character sequence is made active here.
% \begin{macrocode}
\def\lst@IfNextCharsArg#1#2#3{%
\lst@MakeActive{#1}\let\lst@tofind\lst@arg %
\def\@tempa{#2}\def\@tempb{#3}%
\let\lst@eaten\@empty \lst@IfNextChars@}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Catcode changes of characters already read}\label{iCatcodeChangesOfCharactersAlreadyRead}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% Here we define two important macros:
% \begin{macrosyntax}
% \item |\lst@MakeActive{|\meta{character sequence}|}|
%
% stores the character sequence in |\lst@arg|, but all characters become active.
% The string must \emph{not} contain a begin group, end group or escape character (|{}\|); it may contain a left brace, right brace or backslash with other meaning (=catcodes).
% This command would be quite surplus if \meta{character sequence} is not already read by \TeX{} (since such catcodes can be changed easily).
% It is explicitly allowed that the charcaters have been read, e.g.\ in |\def\test{\lst@MakeActive{ABC}}| |\test|!
%
% Note that |\lst@MakeActive| changes |\lccode|s 0--9 without restoring them.
% \item |\lst@IfNextCharActive{|\meta{then part}|}{|\meta{else part}|}|
%
% executes 'then' part if next character behind the arguments is active, and the 'else' part otherwise.
% \end{macrosyntax}
% \TeX{} knows sixteen different catcodes, which say whether a character is a letter, a space, a math shift character, subscript character, and so on.
% A character gets its catcode right after reading it and \TeX{} has no primitive command to change a catcode of characters already read.
% Consider for example |\def\mathmode#1{$#1$}|.
% After that definition there is no chance to say: ''\emph{Print} the two dollar signs and the argument between instead of entering math mode''.
% And if we write |\mathmode{a_i}| and have just entered the macro |\mathmode|, the argument |a_i| is read and it's too late to change the meaning of the subscript character to a printable underbar, for example.
% But that's not the whole truth: We can change character-catcodes of an argument.
% In fact, we replace the characters by characters with same ASCII codes but different catcodes.
% It's not the same but suffices since the result is the same.
% Here we treat the very special case that all characters become active.
% A prototype macro would be
% \begin{verbatim}
% \def\MakeActive#1{\lccode`\~=`#1\lowercase{\def\lst@arg{~}}}|\end{verbatim}
% But this macro handles a single character only:
% The |\lowercase| changes the ASCII code of |~| to that of |#1| since we have said that |~| is the lower case version of |#1|.
% Fortunately the |\lowercase| doesn't change the catcode, so we have an active version of |#1|.
% Note that |~| is usually active.
%
% \begin{macro}{\lst@MakeActive}
% We won't do this character by character.
% To increase speed we change nine characters at the same time (if nine characters are left).
% We get the argument, empty |\lst@arg| and begin a loop:
% \begin{macrocode}
\def\lst@MakeActive#1{%
\let\lst@arg\@empty \lst@MakeActive@#1%
\relax\relax\relax\relax\relax\relax\relax\relax\relax}
% \end{macrocode}
% There are nine |\relax|es since |\lst@MakeActive@| has nine parameters and we don't want any problems in the case that |#1| is empty.
% We need nine active characters now instead of a single |~|.
% We make these catcode changes local and define the coming macro |\global|.
% \begin{macrocode}
\begingroup
\catcode`\^^@=\active \catcode`\^^A=\active \catcode`\^^B=\active %
\catcode`\^^C=\active \catcode`\^^D=\active \catcode`\^^E=\active %
\catcode`\^^F=\active \catcode`\^^G=\active \catcode`\^^H=\active %
% \end{macrocode}
% First we |\let| the next operation be |\relax|.
% This aborts our loop for processing all characters (default and possibly changed later).
% Then we look if we have at least one character.
% If this is not the case, the loop terminates and all is done.
% \begin{macrocode}
\gdef\lst@MakeActive@#1#2#3#4#5#6#7#8#9{\let\lst@next\relax %
\ifx#1\relax %
\else \lccode`\^^@=`#1%
% \end{macrocode}
% Otherwise we say that |^^@|=chr(0) is the lower case version of the first character.
% Then we test the second character.
% If there is none, we append the lower case |^^@| to |\lst@arg|.
% Otherwise we say that |^^A|=chr(1) is the lower case version of the second character and we test the next argument, and so on.
% \begin{macrocode}
\ifx#2\relax %
\lowercase{\lst@lAddTo\lst@arg{^^@}}%
\else \lccode`\^^A=`#2%
\ifx#3\relax %
\lowercase{\lst@lAddTo\lst@arg{^^@^^A}}%
\else \lccode`\^^B=`#3%
\ifx#4\relax %
\lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B}}%
\else \lccode`\^^C=`#4%
\ifx#5\relax %
\lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C}}%
\else \lccode`\^^D=`#5%
\ifx#6\relax %
\lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D}}%
\else \lccode`\^^E=`#6%
\ifx#7\relax %
\lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D^^E}}%
\else \lccode`\^^F=`#7%
\ifx#8\relax %
\lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D^^E^^F}}%
\else \lccode`\^^G=`#8%
\ifx#9\relax %
\lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D^^E^^F^^G}}%
% \end{macrocode}
% If nine characters are present, we append (lower case versions of) nine active characters and call this macro again via redefining |\lst@next|.
% \begin{macrocode}
\else \lccode`\^^H=`#9%
\lowercase{\lst@lAddTo\lst@arg{^^@^^A^^B^^C^^D^^E^^F^^G^^H}}%
\let\lst@next\lst@MakeActive@ %
\fi \fi \fi \fi \fi \fi \fi \fi \fi %
\lst@next}
\endgroup
% \end{macrocode}
% This |\endgroup| restores the catcodes of chr(0)--chr(8), but not the catcodes of the characters inside |\lst@MakeActive@| since they are already read.
% \end{macro}
%
% \begin{macro}{\lst@IfNextCharActive}
% The implementation is easy now: We compare the character |#3| with its active version |\lowercase{~}|.
% Note that the right brace between |\ifx~| and |#3| ends the |\lowercase|.
% The |\egroup| before restores the |\lccode|.
% \begin{macrocode}
\def\lst@IfNextCharActive#1#2#3{%
\bgroup \lccode`\~=`#3\lowercase{\egroup %
\ifx~}#3%
\def\lst@next{#1#3}%
\else %
\def\lst@next{#2#3}%
\fi \lst@next}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{An application to \ref{iCatcodeChangesOfCharactersAlreadyRead}}\label{iAnApplicationTo}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% We need a brief look on how the listing processing works.
% Right before processing a listing we redefine all characters, for example to preserve successive spaces or to give the tabulator a different meaning.
% More precisely, each character becomes active in the sense of \TeX, but that's not so important now.
% After the listing we switch back to the original meanings and all is fine.
% If an environment is used inside an argument the listing is already read when the environment is executed and we can do nothing to preserve the characters.
% However, (under certain circumstances) the environment can be used inside an argument --- that's at least what I've said in the user's guide.
% And now we have to work for it coming true.
% We define the macro
% \begin{macrosyntax}
% \item |\lstenv@AddArg{|\meta{\TeX{} material (already read)}|}|
% \end{macrosyntax}
% which \emph{appends} a 'verbatim' version of the argument to |\lstenv@arg|, but all appended characters are active.
% Since it's not a character to character conversion, 'verbatim' needs to be explained.
% All characters can be typed in as they are, except |\|, |{|, |}| and |%|.
% If you want one of these, you must write |\\|, |\{|, |\}| or |\%| instead.
% If two spaces should follow each other, the second (third, fourth, \ldots) space must be entered as |\|\textvisiblespace.
%
% \begin{macro}{\lstenv@AddArg}
% We call a submacro (similar to |\zap@space|) to preserve single spaces.
% \begin{macrocode}
\def\lstenv@AddArg#1{\lstenv@AddArg@#1 \@empty}
% \end{macrocode}
% We will need an active space:
% \begin{macrocode}
\begingroup \lccode`\~=`\ \relax \lowercase{%
% \end{macrocode}
% We make all characters upto the first space (with catcode 10) active and append these (plus an active space) to |\lstenv@arg|.
% If we haven't found the end |\@empty| of the input, we continue the process.
% \begin{macrocode}
\gdef\lstenv@AddArg@#1 #2{%
\lst@MakeActive{#1}%
\ifx\@empty#2\expandafter%
\lst@lAddTo\expandafter\lstenv@arg\expandafter{\lst@arg}%
\else \expandafter%
\lst@lAddTo\expandafter\lstenv@arg\expandafter{\lst@arg~}%
\expandafter\lstenv@AddArg@ %
\fi #2}
% \end{macrocode}
% Finally we end the |\lowercase| and close a group.
% \begin{macrocode}
}\endgroup
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{How to define \lst-aspects}\label{iHowToDefineLstAspects}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% This section contains commands used in defining the style and language aspects.
% There are two command classes: one extends the internal capabilities, and the other actually defines the aspects.
% \begin{macrosyntax}
% \item |\lst@Aspect{|\meta{aspect name}|}{|\meta{definition}|}|
%
% is the one and only command in the latter class.
% It defines the aspect using the \textsf{keyval} package.
%
% \item |\lst@AddToHook||{|\meta{name of hook}|}{|\meta{\TeX{} material}|}|
%
% \item |\lst@AddToHookAtTop||{|\meta{name of hook}|}{|\meta{\TeX{} material}|}|
%
% Both add \TeX{} material at predefined points.
% The first command appends the code, whereas the second places it in front of existing hook material.
% \end{macrosyntax}
% The following hooks are supported (possibly not up to date):
% \begin{center}\begin{tabular}{rp{0.6\linewidth}}
% name of hook & point/aim of execution\\ \hline
% |InitVars| & initializes variables each listing\\
% |ExitVars| & deinits variables each listing\\
% |OnExit| & executed at the very end of typesetting\\
% |EveryLine| & called at the beginning of each line\\
% |EOL| & executed after printing a source code line\\
% |InitVarsEOL| & prepares variables for the next line\\
% |EndGroup| & executed whenever the package closes a group (end of comment or string, e.g.)\\
% |Output| & called before a printing unit with letters and digits is typeset\\
% |OutputOther| & called before any other printing unit is typeset\\
% |BeforeSelectCharTable| & executed before the package changes the character table\\
% |SelectCharTable| & executed after the package has selected the standard character table\\
% &\\
% |SetStyle| & called before |\lststy@|\meta{style}\\
% |SetLanguage| & called before |\lstlang@|\meta{language}|@|\meta{dialect}\\
% \end{tabular}\end{center}
% For example, the hooks make keywords case insensitive (if necessary) before the package processes a listing and call the keyword style before a keyword is printed.
%
% \begin{macro}{\lst@Aspect}
% The command defines the aspect only if not already present.
% |\lst@ifnew| becomes true (if and) only if a new aspect is defined.
% \begin{macrocode}
\def\lst@Aspect#1{%
\@ifundefined{KV@lst@#1}%
{\let\lst@ifnew\iftrue}{\let\lst@ifnew\iffalse}%
\lst@ifnew %
%<info> \lst@InfoInfo{New aspect `#1'}%
\else %
%<info> \lst@InfoWarning{Gobble aspect `#1'}%
\expandafter\@gobblefour %
\fi %
\lstdefine@key{lst}{#1}}
% \end{macrocode}
% Now come renamed copies from two \textsf{keyval} macros, but the key definitions are made globally.
% \begin{macrocode}
\def\lstdefine@key#1#2{%
\@ifnextchar[{\lstKV@def{#1}{#2}}{\global\@namedef{KV@#1@#2}####1}}
\def\lstKV@def#1#2[#3]{%
\global\@namedef{KV@#1@#2@default\expandafter}\expandafter %
{\csname KV@#1@#2\endcsname{#3}}%
\global\@namedef{KV@#1@#2}##1}
% \end{macrocode}
% \begin{macrocode}
\let\lst@ifnew\iftrue % init
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@AddToHook}
% \begin{macro}{\lst@AddToHookAtTop}
% The definitions are mainly in terms of |\lst@AddTo| and |\lst@AddToAtTop|.
% But we test whether the hook already exists.
% \begin{macrocode}
\def\lst@AddToHook#1{%
\lst@ifnew %
\@ifundefined{lsthk@#1}{%
%<info> \lst@InfoInfo{New hook `#1'}%
\expandafter\gdef\csname lsthk@#1\endcsname{}}{}%
\def\lst@next{\lst@AddToHook@\lst@AddTo{#1}}%
\expandafter\lst@next %
\else %
\expandafter\@gobble %
\fi}
% \end{macrocode}
% The submacro makes it possible to use \texttt{if}s inside the second argument (which is the third here).
% \begin{macrocode}
\long\def\lst@AddToHook@#1#2#3{%
\expandafter#1\csname lsthk@#2\endcsname{#3}}
% \end{macrocode}
% \begin{TODO}
% The usage of |\lst@ifnew| is still unsatisfactory:
% Defining an aspect and its hooks twice doesn't add the \TeX\ material a second time, but defining hooks and then the aspect would do so.
% \end{TODO}
% \begin{macrocode}
\def\lst@AddToHookAtTop#1{%
\lst@ifnew %
\@ifundefined{lsthk@#1}{%
%<info> \lst@InfoInfo{New hook `#1'}%
\expandafter\gdef\csname lsthk@#1\endcsname{}}{}%
\def\lst@next{\lst@AddToHook@\lst@AddToAtTop{#1}}%
\expandafter\lst@next %
\else %
\expandafter\@gobble %
\fi}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@AddTo}
% \begin{macro}{\lst@AddToAtTop}
% These macros add the second argument to the macro |#1|.
% But the definition is global!
% \begin{macrocode}
\long\def\lst@AddTo#1#2{%
\expandafter\gdef\expandafter#1\expandafter{#1#2}}
% \end{macrocode}
% We need a couple of |\expandafter|s now.
% Simply note that we have\\
% {\small\hspace*{2em}
% |\expandafter\gdef\expandafter#1\expandafter{\lst@temp|$\langle$\textit{contents of }|#1|$\rangle$|}|
% }\\
% after the first phase of expansion.
% \begin{macrocode}
\def\lst@AddToAtTop#1#2{\def\lst@temp{#2}%
\expandafter\expandafter\expandafter\gdef %
\expandafter\expandafter\expandafter#1%
\expandafter\expandafter\expandafter{\expandafter\lst@temp#1}}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@lAddTo}
% A local version of |\lst@AddTo|.
% \begin{macrocode}
\def\lst@lAddTo#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
% \end{macrocode}
% \end{macro}
%
% \begingroup
% \noindent Since some hooks are unused and never defined by the hook macros above, we define them here:
% \begin{macrocode}
\global\let\lsthk@OutputOther\@empty
\global\let\lsthk@SetStyle\@empty
\global\let\lsthk@SetLanguage\@empty
\global\let\lsthk@PreSet\@empty
\global\let\lsthk@PostSet\@empty
% \end{macrocode}
% \endgroup
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Interfacing with \textsf{keyval}}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% The \textsf{keyval} package passes the value via the one and only paramater |#1| to the definition part of the aspect macro.
% The following commands may be used to analyse the value.
% \begin{macrosyntax}
% \item |\lstKV@SetIfKey|\meta{macro}|{#1}|
%
% \meta{macro} becomes true (more precisely |\iftrue|) if the first character of |#1| equals |t| or |T|.
% It becomes false otherwise.
%
% \item |\lstKV@OptArg|\meta{submacro}|[|\meta{default arg.}|]{#1}|
%
% calls \meta{submacro} with |#1| and with inserted |[|\meta{default arg.}|]| if |#1| has no optional argument.
% \end{macrosyntax}
%
% \begin{macro}{\lstKV@SetIfKey}
% We simply test the first character of |#2|.
% \begin{macrocode}
\def\lstKV@SetIfKey#1#2{\lstKV@SetIfKey@#1#2\relax}
\def\lstKV@SetIfKey@#1#2#3\relax{\lowercase{%
\expandafter\let\expandafter#1%
\csname \ifx #2t}iftrue\else iffalse\fi\endcsname}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstKV@OptArg}
% We read the arguments and insert default if necesary, what else?
% \begin{macrocode}
\def\lstKV@OptArg#1[#2]#3{\lstKV@OptArg@{#1}{#2}#3\@}
\def\lstKV@OptArg@#1#2{%
\@ifnextchar[{\lstKV@OptArg@@{#1}}%
{\lstKV@OptArg@@{#1}[#2]}}
\def\lstKV@OptArg@@#1[#2]#3\@{#1[#2]{#3}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstset}
% Finally this main user interface macro:
% \begin{macrocode}
\def\lstset#1{\lsthk@PreSet\setkeys{lst}{#1}\lsthk@PostSet}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Internal modes}\label{iInternalModes}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@mode}
% \begin{macro}{\lst@EnterMode}
% \begin{macro}{\lst@LeaveMode}
% While typesetting a listing we will enter 'modes' to distinguish comments from strings, comment lines from single comments, \TeX\ comment lines from fixed comment lines, and so on.
% The counter |\lst@mode| keeps the current mode number.
% \begin{macrocode}
\newcount\lst@mode
% \end{macrocode}
% Each mode opens a group level, stores the mode number and execute mode specific tokens.
% Moreover we keep all these changes in mind (locally).
% \begin{macrocode}
\def\lst@EnterMode#1#2{%
\bgroup \lst@mode=#1\relax #2%
\lst@lAddTo\lst@entermodes{\lst@EnterMode{#1}{#2}}}
% \end{macrocode}
% Leaving a mode simply closes the group and calls the hook |\lsthk@EndGroup|.
% \begin{macrocode}
\def\lst@LeaveMode{\egroup\lsthk@EndGroup}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{InitVars}{\let\lst@entermodes\@empty}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lst@NewMode}
% defines a new mode number.
% We simply use |\mathchardef| and advance the number in |\lst@newmode|, which is a macro --- we don't waste another counter.
% \begin{macrocode}
\def\lst@NewMode#1{%
\ifx\@undefined#1%
\global\mathchardef#1=\lst@newmode\relax %
\lst@mode=\lst@newmode\relax \advance\lst@mode\@ne %
\edef\lst@newmode{\the\lst@mode}%
\fi}
% \end{macrocode}
% We start with number 0.
% The negative range is reserved for nested comments.
% \begin{macrocode}
\def\lst@newmode{0}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@nomode}
% \begin{macro}{\lst@Pmode}
% The very first mode initializes |\lst@mode| (every listing).
% The other mode indicates active listing processing.
% \begin{macrocode}
\lst@NewMode\lst@nomode
\lst@AddToHook{InitVars}{\lst@modefalse \lst@mode\lst@nomode}
\lst@NewMode\lst@Pmode
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@modetrue}
% \begin{macro}{\lst@modefalse}
% If |\lst@ifmode| is true, no mode change is allowed --- except leaving the mode.
% \begin{macrocode}
\def\lst@modetrue{\let\lst@ifmode\iftrue}
\def\lst@modefalse{\let\lst@ifmode\iffalse}
% \end{macrocode}
% Note: |\lst@ifmode| is \emph{not} obsolete since |\lst@mode|$\neq$|\lst@nomode| does \emph{not} imply |\lst@ifmode|$=$|\iftrue|.
% And even the other implication is not true.
% It will happen that we enter a mode without setting |\lst@ifmode| true, and we'll set it true without assigning any mode!
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@InterruptModes}
% \begin{macro}{\lst@ReenterModes}
% Since we kept all mode changes in mind, it is possible two interrupt and re-enter the current mode.
% This is useful for \TeX\ comment lines, for example.
% \begin{macrocode}
\def\lst@InterruptModes{%
\ifx\lst@entermodes\@empty\else %
\global\let\lst@reenter\lst@entermodes %
\lst@LeaveAllModes %
\fi}
% \end{macrocode}
% The last |\ifx| is not necessay since empty |\lst@entermodes| implies that we don't leave any mode.
% But we need the |\ifx| in the following macro since empty |\lst@reenter| doesn't tell us anything about the current mode.
% \begin{macrocode}
\def\lst@ReenterModes{%
\ifx\lst@reenter\@empty\else %
\lst@LeaveAllModes \lst@reenter %
\global\let\lst@reenter\@empty %
\fi}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{InitVars}{\global\let\lst@reenter\@empty}
% \end{macrocode}
% Note that these macros can't be nested:
% If you 'interrupt modes', enter some modes and say 'interrupt modes' again, then two 're-enter modes' will \emph{not} take you back in front of the first 'interrupt modes'.
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@LeaveAllModes}
% This is some kind of emergency macro.
% Since any mode is terminated by closing a group, leaving all modes means closing groups until the mode equals |\lst@nomode|.
% We'll need that macro to end a listing correctly.
% \begin{macrocode}
\def\lst@LeaveAllModes{%
\ifnum\lst@mode=\lst@nomode %
\expandafter\lsthk@EndGroup %
\else %
\expandafter\egroup\expandafter\lst@LeaveAllModes %
\fi}
\lst@AddToHook{ExitVars}{\lst@LeaveAllModes}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@egroupmode}
% We allocate a 'processing mode' and define a general purpose 'egroup' mode: close a group at end of line.
% \begin{macrocode}
\lst@NewMode\lst@egroupmode
\lst@AddToHook{EOL}
{\ifnum\lst@mode=\lst@egroupmode \lst@LeaveMode \fi}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Styles and languages}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@Normalize}
% normalizes the contents of the macro |#1| by making all characters lower case and stripping off spaces.
% \begin{macrocode}
\def\lst@Normalize#1{%
\lowercase\expandafter{\expandafter\edef\expandafter#1%
\expandafter{\expandafter\zap@space#1 \@empty}}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstdefinestyle}
% The internal macro name of a style is |\lststy@|\emph{the style} (normalized).
% If called, it simply sets the keys to given values.
% \begin{macrocode}
\newcommand\lstdefinestyle[2]{%
\def\lst@temp{lststy@#1}\lst@Normalize\lst@temp %
\global\@namedef\lst@temp{\setkeys{lst}{#2}}}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{style}
% We give an error message if the necessary macro doesn't exist.
% \begin{macrocode}
\lst@Aspect{style}
{\def\lst@temp{lststy@#1}\lst@Normalize\lst@temp %
\@ifundefined\lst@temp %
{\PackageError{Listings}{Style `#1' undefined}%
{You might have misspelt the name here or before.^^J%
Type <RETURN> to proceed without changing the style.}}%
% \end{macrocode}
% Otherwise we execute the hook and call the macro.
% \begin{macrocode}
{\lsthk@SetStyle \csname\lst@temp\endcsname %
%<info> \lst@InfoInfo{\expandafter\string %
%<info> \csname\lst@temp\endcsname\space called}%
}}
% \end{macrocode}
% \begin{TODO}
% It's easy to crash the listings package with |style| (and also with |language|).
% Define |\lstdefinestyle{crash}{style=crash}| and write |\lstset{style=crash}|.
% \TeX's capacity will exceed (parameter stack size), sorry.
% Only bad girls use such recursive calls, but only good girls use this package.
% Thus this problem is of minor interest.
% \end{TODO}
% \end{aspect}
%
% \begin{macro}{\lstdefinelanguage}
% Nearly |\lstdefinestyle|:
% \begin{macrocode}
\newcommand\lstdefinelanguage[3][]{%
\def\@tempa{#2@#1}\lst@Normalize\@tempa %
\global\@namedef{lstlang@\@tempa}{\lstset{#3}}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstdefinedrvlanguage}
% The driver file \texttt{lstpascal.sty} contains a couple of Pascal dialects.
% It is unnecessary to hold all these dialects in memory if the user selects Standard Pascal only.
% There are different scopes:
% \begin{itemize}
% \item[--] All code outside any (style or language) definition is executed.
% Definitions should be |\global| since a driver file is input inside a group.
% Note also that |@| is a letter and |"| has catcode 12 (other).
% \item[--] All languages declared with |\lstdefinelanguage| are defined.
% \item[--] A language declared with |\lstdefinedrvlanguage| is defined if and only if the user has requested that language.
% \end{itemize}
% We either do the definition or drop it:
% \begin{macrocode}
\newcommand\lstdefinedrvlanguage[3][]{%
\def\@tempa{lstlang@#2@#1}\lst@Normalize\@tempa %
\ifx\@tempa\lst@requested %
\global\@namedef{\@tempa}{\lstset{#3}}%
\fi}
% \end{macrocode}
% \begin{TODO}
% The command syntax is liable to changes.
% I conjecture that it will be something like the following.
% \begin{macrosyntax}
% \item[0.2] |\lstdefinedrvlanguage|[|[|\meta{dialect}|]|]|{|\meta{language}|}|\\
% \qquad[|[|\meta{base dialect}|]|]|{|\meta{base language (e.g.\ empty)}|}|\\
% \qquad|{|\meta{key=value list}|}|\\
% \qquad[|[|\meta{list of extras (keywordcomments,texcs,etc.)}|]|]
% \end{macrosyntax}
% To make 'extras' user assessible (without loading a language) a command |\lstloadextras| would be nice.
% In any case such a macro is needed to load the extras for the supported languages.
% All in all there should be the following files in future: The kernel |listings.sty|, the language definitions in |lstdrvrs.sty| (or |lstdef.sty|?) and extras in a file |lstextra.sty|.
% \end{TODO}
% \end{macro}
%
% \begin{macro}{\lstloadlanguages}
% We iterate through the list and locate and load each language.
% \begin{macrocode}
\def\lstloadlanguages#1{\lstloadlanguages@#1,\relax,}
\def\lstloadlanguages@#1,{%
\ifx\relax#1\@empty \else %
\lstKV@OptArg\lstloadlanguages@@[]{#1}%
\expandafter\lstloadlanguages@ %
\fi}
\def\lstloadlanguages@@[#1]#2{%
\lst@LocateLanguage[#1]{#2}%
\@ifundefined{\lst@requested}%
{{\catcode`\^^M=9\catcode`\"=12\makeatletter %
\input{\lst@driver.sty}}}%
{}}
\@onlypreamble\lstloadlanguages
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{language}
% If the language macro |\lstlang@|\emph{language}|@|\emph{dialect} doesn't exist, we must load the driver file.
% In that case the character |@| becomes a letter and we change the catcode of the double quote for compatibility with \texttt{german.sty}.
% Moreover we make the EOL character being ignored (which removes unwanted spaces if we've forgotten |%| at end of line).
% \begin{macrocode}
\lst@Aspect{language}{\lstKV@OptArg\lstlanguage@[]{#1}}
\def\lstlanguage@[#1]#2{%
\lst@LocateLanguage[#1]{#2}%
\@ifundefined{\lst@requested}%
{{\catcode`\^^M=9\catcode`\"=12\makeatletter %
\input{\lst@driver.sty}}}{}%
% \end{macrocode}
% We give an error message, if the language/dialect is undefined now.
% \begin{macrocode}
\@ifundefined{\lst@requested}%
{\PackageError{Listings}%
{\ifx\@empty\lst@dialect@\else \lst@dialect@\space of \fi %
\lst@language@\space undefined}{The driver file is not
loadable or doesn't support the language.^^J%
Type <RETURN> to proceed without changing the language.}}%
% \end{macrocode}
% Otherwise we execute the hook and select the language.
% \begin{macrocode}
{\lsthk@SetLanguage %
%<info> \lst@InfoInfo{\expandafter\string %
%<info> \csname\lst@requested\endcsname\space called}%
\csname\lst@requested\endcsname %
\def\lst@language{#1}\lst@Normalize\lst@language %
\def\lst@dialect{#2}\lst@Normalize\lst@dialect}}
% \end{macrocode}
% \end{aspect}
%
% \begin{aspect}{defaultdialect}
% We simply store the dialect.
% \begin{macrocode}
\lst@Aspect{defaultdialect}{\lstKV@OptArg\lstdefaultdialect@[]{#1}}
\def\lstdefaultdialect@[#1]#2{%
\def\lst@temp{#2}\lst@Normalize\lst@temp %
\global\@namedef{lstdd@\lst@temp}{#1}}
% \end{macrocode}
% \end{aspect}
%
% Languages might have a user name and a different internal name.
% Moreover we don't always use the standard driver file |lst|\meta{language}|.sty|.
% If the user writes |language=[fuu]foo|, this could mean that we select (internally) dialect |faa| of language |fee|, which is located in driver file |fii.sty|.
% We define the following macros:
% \begin{macrosyntax}
% \item |\lst@DriverLocation{|\meta{language}|}{|\meta{file name without extension}|}|
%
% Afterwards the package inputs the given driver file to load the language.
%
% \item |\lst@LocateLanguage[|\meta{dialect}|]{|\meta{language}|}|
%
% returns the driver file name in |\lst@driver| and |\lst@requested| contains name of driver macro (i.e.\ with prefix |lstlang@|, without backslash).
% The macro automatically chooses aliases.
% \end{macrosyntax}
% All language and dialect arguments are standardized, i.e.\ we make them free of spaces and lower case.
%
% \begin{macro}{\lstalias}
% The names are stored in |\lsta@|\emph{language}|@|\emph{dialect} and |\lstaa@|\emph{language}.
% \begin{macrocode}
\newcommand\lstalias{\@ifnextchar[{\lstalias@}{\lstalias@@}}
% \end{macrocode}
% \begin{macrocode}
\def\lstalias@[#1]#2[#3]#4{%
\def\lst@temp{lsta@#2@#1}\lst@Normalize\lst@temp %
\global\@namedef{\lst@temp}{#4@#3}}
% \end{macrocode}
% \begin{macrocode}
\def\lstalias@@#1#2{%
\def\lst@temp{lstaa@#1}\lst@Normalize\lst@temp %
\global\@namedef{\lst@temp}{#2}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@DriverLocation}
% We simply define a macro containing the file name.
% \begin{macrocode}
\def\lst@DriverLocation#1#2{%
\def\lst@temp{lstloc@#1}\lst@Normalize\lst@temp %
\expandafter\gdef\csname\lst@temp\endcsname{#2}%
\expandafter\lst@Normalize\csname\lst@temp\endcsname}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@LocateLanguage}
% First we test for a language alias, \ldots
% \begin{macrocode}
\def\lst@LocateLanguage[#1]#2{%
\def\lst@language@{#2}\lst@Normalize\lst@language@ %
\@ifundefined{lstaa@\lst@language@}{}%
{\edef\lst@language@{\csname lstaa@\lst@language@\endcsname}%
\lst@Normalize\lst@language@}%
% \end{macrocode}
% then we set the default dialect if necessary.
% \begin{macrocode}
\def\lst@dialect@{#1}%
\ifx\@empty\lst@dialect@ %
\@ifundefined{lstdd@\lst@language@}{}%
{\expandafter\let\expandafter\lst@dialect@ %
\csname lstdd@\lst@language@\endcsname}%
\fi %
\lst@Normalize\lst@dialect@ %
% \end{macrocode}
% Now we are ready for an alias for a language dialect.
% \begin{macrocode}
\edef\lst@requested{\lst@language@ @\lst@dialect@}%
\@ifundefined{lsta@\lst@requested}{}%
{\expandafter\let\expandafter\lst@requested %
\csname lsta@\lst@requested\endcsname %
\lst@Normalize\lst@requested}%
% \end{macrocode}
% Finally we get the driver file name and set the default dialect.
% \begin{macrocode}
\expandafter\lst@LocateLanguage@\lst@requested\relax}
\def\lst@LocateLanguage@#1@#2\relax{%
\edef\lst@driver{\@ifundefined{lstloc@#1}{lst#1}%
{\csname lstloc@#1\endcsname}}%
\ifx\@empty#2\@empty %
\@ifundefined{lstdd@#1}%
{\def\lst@dialect@{#2}}%
{\expandafter\let\expandafter\lst@dialect@ %
\csname lstdd@#1\endcsname}%
\fi %
\edef\lst@requested{lstlang@#1@\lst@dialect@}%
\lst@Normalize\lst@requested}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \section{Typesetting a listing}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@lineno}
% This counter keeps the current line number.
% A register is global if and only if the allocation line shows |% \global|.
% \begin{macrocode}
\newcount\lst@lineno \global\lst@lineno\@ne % \global
% \end{macrocode}
% The counter is initialized and advances every line (which means |\everypar|).
% \begin{macrocode}
\lst@AddToHook{InitVars}
{\global\lst@lineno\@ne %
\expandafter\everypar\expandafter{\the\everypar %
\global\advance\lst@lineno\@ne}}
% \end{macrocode}
% And we (try to) ensure correct line numbers for continued listings.
% \begin{macrocode}
\lst@AddToHook{ExitVars}
{\ifx\lst@NewLine\relax\else %
\global\advance\lst@lineno-2\relax %
\setbox\@tempboxa\vbox{\lst@NewLine}%
\fi}
% \end{macrocode}
% \begin{TODO}
% We only try to.
% If there is source code before |\end{lstlisting}|, it goes wrong: the line number is one too less.
% \end{TODO}
% \end{macro}
%
% \begin{macro}{\lst@PrintFileName}
% makes use of |\lst@ReplaceIn|:
% \begin{macrocode}
\def\lst@PrintFileName#1{%
\def\lst@arg{#1}%
\lst@ReplaceIn\lst@arg{_\textunderscore $\textdollar -\textendash}%
\lst@arg}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@SetName}
% As proposed by \lsthelper{Boris Veytsman}{boris@plmsc.psu.edu}{1998/03/22}{listing name accessible for user} the name of a listing (file name or argument to the environment) is user accessible now.
% It is set using this macro:
% \begin{macrocode}
\def\lst@SetName#1{%
\gdef\lst@intname{#1}\global\let\lstintname\lst@intname %
\let\lst@arg\lst@intname %
\lst@ReplaceIn\lst@arg{_\textunderscore $\textdollar -\textendash}%
\global\let\lstname\lst@arg}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{List of listings}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\listoflistings}
% Instead of imitating |\listoffigures| we make some local adjustments and call |\tableofcontents|.
% This has the advantage that redefinitions (e.g.\ without any |\MakeUppercase| inside) also take effect on the list of listings.
% \begin{macrocode}
\newcommand\listoflistings{\bgroup %
\let\contentsname\listlistingsname %
\let\lst@temp\@starttoc \def\@starttoc##1{\lst@temp{lol}}%
\tableofcontents \egroup}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\listlistingsname}
% Simply the header name:
% \begin{macrocode}
\newcommand\listlistingsname{Listings}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@AddToLOL}
% adds an entry to the list of listings.
% The first parameter is the name of the listing and the second is unused so far.
% \begin{macrocode}
\newcommand\lst@AddToLOL[2]{%
\ifx\@empty#1\@empty \else %
\addtocontents{lol}{\protect\lstlolline{#1}{#2}%
{\lst@language}{\thepage}}%
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstlolline}
% prints one 'lol' line.
% Using |\lst@PrintFileFile| removes a bug first reported by \lsthelper{Magne Rudshaug}{magne@ife.no}{1998/01/09}{_ and list of listings}.
% \begin{macrocode}
\newcommand\lstlolline[4]{%
\@dottedtocline{1}{1.5em}{2.3em}{\lst@PrintFileName{#1}}{#4}}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Init and EOL}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% We need some macros to initialize registers and variables before typesetting a listing and for the update every line.
%
% \begin{macro}{\lst@Init}
% The argument |#1| (assigned at the end) is either |\relax| or |\lstenv@backslash| since the backslash has a special meaning for the environment.
% The line number is used as current label (proposed by \lsthelper{Boris Veytsman}{boris@plmsc.psu.edu}{1998/03/25}{make line numbers referenced via \label and \ref}).
% The end of line character chr(13)=|^^M| controls the processing, see the definition of |\lst@MProcessListing| below.
% The vertical space in the macro code is for clarity.
% \begin{macrocode}
\def\lst@Init#1{%
\begingroup \normalbaselines \smallbreak %
\def\@currentlabel{\the\lst@lineno}%
\lst@prelisting %
% \end{macrocode}
% \begin{macrocode}
\lsthk@BeforeSelectCharTable %
\normalbaselines \everypar{\lsthk@EveryLine}%
\lsthk@InitVars \lsthk@InitVarsEOL %
% \end{macrocode}
% \begin{macrocode}
\csname lstPre@\lst@language\endcsname %
\csname lstPre@\lst@language @\lst@dialect\endcsname %
\lstCC@Let{"000D}\lst@MProcessListing %
\let\lstCC@Backslash#1%
\lst@EnterMode{\lst@Pmode}{\lst@SelectCharTable}}
% \end{macrocode}
% Note: From version 0.19 on 'listing processing' is implemented as an internal mode, namely a mode with special character table.
% \begin{macrocode}
\lst@AddToHook{InitVars}
{\rightskip\z@ \leftskip\z@ \parfillskip=0pt plus 1fil %
\let\par\@@par}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@DeInit}
% Here we output the remaining characters, update some variables and do some other things.
% \begin{macrocode}
\def\lst@DeInit{%
\lst@PrintToken \lst@EOLUpdate \par\removelastskip %
\lsthk@ExitVars %
\smallbreak\lst@postlisting %
\endgroup}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@EOLUpdate}
% This macro seems to be obsolete since in version 0.19 it degenerates to
% \begin{macrocode}
\def\lst@EOLUpdate{\lsthk@EOL \lsthk@InitVarsEOL}%
% \end{macrocode}
% But in future it might come in handy again.
% \end{macro}
%
% \begin{macro}{\lst@MProcessListing}
% This is what we have to do at EOL while processing a listing.
% We output all remaining characters and update the variables.
% We call |\endinput| if the next line number is greater than the last printing line.
% Finally we gobble characters to come to beginning of line.
% \begin{macrocode}
\def\lst@MProcessListing{%
\lst@PrintToken \lst@EOLUpdate %
\ifnum\lst@lastline<\lst@lineno \expandafter\endinput \fi %
\lst@BOLGobble}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@BOLGobble}
% But this is initially |\relax|.
% \begin{macrocode}
\let\lst@BOLGobble\relax
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{The input command}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{TODO}
% There is a conflict concerning |\lst@firstline|: It contains either the line number of the first code line or line number.
% This must be clarified before |lstlisting| can use the keys |first| and |last|.
% \end{TODO}
%
% \begin{aspect}{print}
% \begin{aspect}{first}
% \begin{aspect}{last}
% These aspects affect the input command only, not the environment.
% \begin{macrocode}
\lst@Aspect{print}[t]{\lstKV@SetIfKey\lst@ifprint{#1}}
\lst@Aspect{first}{\def\lst@firstline{#1}}
\lst@Aspect{last}{\def\lst@lastline{#1}}
\lstset{print=true}% init
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}
%
% \begin{macro}{\lstinputlisting}
% We define the main command.
% First we take care of the optional paramater and set it to $[1,9999999]$ if none is given.
% \begin{macrocode}
\newcommand\lstinputlisting[2][]{%
\begingroup %
\def\lst@firstline{1}\def\lst@lastline{9999999}\lstset{#1}%
\IfFileExists{#2}{\lst@InputListing{#2}}%
{\filename@parse{#2}%
\edef\reserved@a{\noexpand\lst@MissingFileError
{\filename@area\filename@base}%
{\ifx\filename@ext\relax tex\else\filename@ext\fi}}%
\reserved@a}%
\endgroup %
\lsthk@OnExit}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@MissingFileError}
% is a derivation of \LaTeX's |\@missingfileerror|:
% \begin{macrocode}
\def\lst@MissingFileError#1#2{%
\typeout{^^J! Package Listings Error: File `#1.#2' not found.^^J^^J%
Type X to quit or <RETURN> to proceed,^^J%
or enter new name. (Default extension: #2)^^J}%
\message{Enter file name: }%
{\endlinechar\m@ne \global\read\m@ne to\@gtempa}%
% \end{macrocode}
% Typing |x| or |X| exits.
% \begin{macrocode}
\ifx\@gtempa\@empty \else %
\def\reserved@a{x}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
\def\reserved@a{X}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
% \end{macrocode}
% In all other cases we try the new file name (with default extension).
% \begin{macrocode}
\filename@parse\@gtempa %
\edef\filename@ext{%
\ifx\filename@ext\relax#2\else\filename@ext\fi}%
\edef\reserved@a{\noexpand\IfFileExists %
{\filename@area\filename@base.\filename@ext}%
{\noexpand\lst@InputListing %
{\filename@area\filename@base.\filename@ext}}%
{\noexpand\lst@MissingFileError
{\filename@area\filename@base}{\filename@ext}}}%
\expandafter\reserved@a %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@InputListing}
% The one and only argument is the file name.
% We either add this name to the list of listings or the name plus a bullet to indicate that the listing has been skipped.
% Note that |\lst@Init| takes |\relax| as an argument.
% \begin{macrocode}
\def\lst@InputListing#1{%
\lst@SetName{#1}%
\lst@ifprint %
\lst@AddToLOL{#1}{}%
\lst@Init\relax \lst@SkipUptoFirst \input{#1}\lst@DeInit %
\else %
\lst@AddToLOL{#1$^\bullet$}{}%
\begin{center}%
\footnotesize --- Listing of #1 has been skipped. ---
\end{center}%
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@SkipUptoFirst}
% The end of line character either processes the listing or is responsible for skipping lines upto first printing line.
% \begin{macrocode}
\def\lst@SkipUptoFirst{%
\ifnum\lst@lineno=\lst@firstline\else %
% \end{macrocode}
% To skip input lines we begin a new group level (which makes our changes local) and prohibit mode changes.
% We redefine the end of line character and all output macros becomes equivalent to |\relax|, i.e.\ nothing is typeset.
% \begin{macrocode}
\bgroup \lst@modetrue %
\let\lst@Output\relax \let\lst@OutputOther\relax %
\let\lst@GotoTabStop\relax %
\lstCC@Let{"000D}\lst@MSkipUptoFirst %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@MSkipUptoFirst}
% At the moment we use a fast and not 'everything is looking good' way.
% When |\lst@MSkipUptoFirst| is executed, one input line has already been skipped.
% We end the group opened in |\lst@SkipUptoFirst|.
% This restores the definition of the end of line character chr(13).
% Then we look whether to skip more lines or not.
% \begin{macrocode}
\def\lst@MSkipUptoFirst{\egroup %
\global\advance\lst@lineno\@ne %
\ifnum\lst@lineno=\lst@firstline\else %
\expandafter\lst@MSkipUptoFirst@ %
\fi}
% \end{macrocode}
% The argument of |\lst@MSkipUptoFirst@| ends with the next active chr(13), which means that the next input line is read.
% Again we look whether to skip more lines or not.
% \begin{macrocode}
\begingroup \lccode`\~=`\^^M%
\lowercase{\gdef\lst@MSkipUptoFirst@#1~}{%
\global\advance\lst@lineno\@ne %
\ifnum\lst@lineno=\lst@firstline\else %
\expandafter\lst@MSkipUptoFirst@ %
\fi}
\endgroup
% \end{macrocode}
% \begin{TODO}
% This definition gives rise to a ''runaway argument'' if first line doesn't exist (no |^^M| is found).
%
% We could define |\lst@MSkipUptoFirst| exactly as |\lst@MProcessListing|, except that we start the normal line processing if we reach the first printing line.
% In that case all comments and strings are processed, but not output.
% Everything looks good, even if the first printing line is in the middle of a comment.
% We need to do the following things:
% \begin{enumerate}
% \item Install an \texttt{if} to choose between speed and good looking, which must be noticed in |\lst@SkipUptoFirst|.
% There we must (locally) switch to |\lsttexcloff|.
% \item Call |\lst@BeginDropOutput{\lst@nomode}| in |\lst@SkipUptoFirst| instead of |\bgroup\lst@modetrue| and assigning |\relax|es.
% \item Define |\lst@MSkipUptoFirstExact| by copying |\lst@MProcessListing| and renaming it.
% Replace the |\ifnum| by\vspace*{-0.5\baselineskip}
% \begin{verbatim}
%\ifnum\lst@lineno=lst@firstline %
% \lst@LeaveMode \global\lst@column\z@ \global\lst@pos\z@ %
%\fi\end{verbatim}
% \item Make the fine tuning if necessary.
% \end{enumerate}
% \end{TODO}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{The environment}\label{iTheEnvironment}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@Environment}
% This is the first attempt to provide a general macro, which defines the \lst-environments.
% The syntax comes from \LaTeX's |\newenvironment|:
% \begin{macrosyntax}
% \item |\lst@Environment{|\meta{name}|}[|\meta{number of parameters}|][|\meta{opt.~default~arg.}|]\is|\\
% |{|\meta{begin code}|}|\\
% |{|\meta{end code}|}|
% \end{macrosyntax}
% Note the additional |\is|.
% I should mention that such environments could also be used in command fashion
% \begin{verbatim}
% \lstlisting{my name}
% Here comes the listing.
% \endlstlisting\end{verbatim}
% But now the implementation.
% We define undefined environments only:
% \begin{macrocode}
\def\lst@Environment#1#2\is#3#4{%
\@ifundefined{#1}{\lst@Environment@{#1}{#2}{#3}{#4}}%
{%
%<info> \lst@InfoWarning{Multiple environment `#1'}%
}}
% \end{macrocode}
% A lonely 'end environment' produces an error:
% \begin{macrocode}
\def\lst@Environment@#1#2#3#4{%
\global\@namedef{end#1}{\lstenv@Error{#1}}%
% \end{macrocode}
% The 'main' environment macro defines the environment name (for later use) and calls a submacro (getting all arguments).
% We open a group and redefine the (active) EOL character to be |\relax|.
% This ensures |\@ifnextchar[| not to read characters of the listing --- it reads the active EOL instead.
% \begin{macrocode}
\global\@namedef{#1}{%
\def\lstenv@name{#1}%
\begingroup \lstCC@Let{"000D}\relax %
\csname#1@\endcsname}%
% \end{macrocode}
% The submacro is defined via |\new@command|.
% We misuse |\l@ngrel@x| to make the definition |\global|.
% The submacro defines the first and last line, which are possibly changed by the user's \meta{begin code} |#3|.
% \begin{macrocode}
\let\l@ngrel@x\global %
\expandafter\new@command\csname#1@\endcsname#2%
{\def\lst@firstline{1}\def\lst@lastline{9999999}%
#3%
% \end{macrocode}
% The definition of the string which terminates the environment (|end{lstlisting}| or |endlstlisting|, for example) needs some care since the braces must not have catcodes 1 and 2 (or |\lst@MakeActive| fails).
% We enter them as |\{| and |\}| (with preceding |\noexpand|s).
% \begin{macrocode}
\ifx\@currenvir\lstenv@name %
\edef\lst@temp{end\noexpand\{\lstenv@name\noexpand\}}%
\else %
\edef\lst@temp{end\lstenv@name}%
\fi %
\expandafter\lst@MakeActive\expandafter{\lst@temp}%
\let\lstenv@endstring\lst@arg %
% \end{macrocode}
% We redefine (locally) 'end environment' inside the 'begin environment' macro since ending is legal now.
% Note that the redefinition also works inside a \TeX\ comment line.
% \begin{macrocode}
\@namedef{end#1}{\lst@DeInit #4\endgroup \lsthk@OnExit}%
% \end{macrocode}
% Finally the 'begin environment' macro starts the processing.
% \begin{macrocode}
\lstenv@Process}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstenv@Error}
% have been used above.
% \begin{macrocode}
\def\lstenv@Error#1{\PackageError{Listings}{Extra \string\end#1}%
{I'm ignoring this, since I wasn't doing a \csname#1\endcsname.}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstenv@backslash}
% We have the problem of finding end of environment, and we've already defined the 'end environment' string.
% Coming to a backslash we either end the listing or process a backslash and insert the eaten characters again.
% (Eaten means that these characters have been read (and removed) from the input to test for |\lstenv@endstring|.)
% \begin{macrocode}
\def\lstenv@backslash{%
\lst@IfNextChars\lstenv@endstring %
{\lstenv@End}%
{\lsts@backslash \lst@eaten}}%
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstenv@End}
% This macro is called by the backslash macro and terminates a listing environment:
% We call the 'end environment' macro as a command or using |\end|.
% \begin{macrocode}
\def\lstenv@End{%
\ifx\@currenvir\lstenv@name %
\edef\lst@next{\noexpand\end{\lstenv@name}}%
\else %
\def\lst@next{\csname end\lstenv@name\endcsname}%
\fi %
\lst@next}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstenv@Process}
% First some initialization, then call a submacro.
% \begin{macrocode}
\def\lstenv@Process{%
\lst@Init\lstenv@backslash %
\global\lst@lineno\lst@firstline\relax %
\let\lstenv@ifdropped\iffalse \lstenv@Process@}
% \end{macrocode}
% \begin{macrocode}
\def\lstenv@droppedtrue{\let\lstenv@ifdropped\iftrue}
% \end{macrocode}
% We execute either |\lstenv@ProcessM| or |\lstenv@ProcessJ| according to whether we find an active EOL or a nonactive |^^J|.
% \begin{macrocode}
\begingroup \lccode`\~=`\^^M%
\lowercase{\gdef\lstenv@Process@#1{%
\ifx~#1%
\expandafter\lstenv@ProcessM %
\else\ifx^^J#1%
\expandafter\expandafter\expandafter\lstenv@ProcessJ %
\else %
\lstenv@droppedtrue %
\expandafter\expandafter\expandafter\lstenv@Process@ %
\fi \fi}
}\endgroup
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstenv@DroppedWarning}
% gives a warning if characters have been dropped.
% \begin{macrocode}
\def\lstenv@DroppedWarning{%
\lstenv@ifdropped %
\PackageWarning{Listings}{Text dropped after begin of listing}%
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstenv@ProcessM}
% There is nothing to do if we've found an active EOL, except giving a warning if necessary.
% \begin{macrocode}
\def\lstenv@ProcessM{\lstenv@DroppedWarning \lst@BOLGobble}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstenv@ProcessJ}
% Now comes the horrible scenario: A listing inside an argument.
% We've already worked in section \ref{iAnApplicationTo} for this.
% Here we must get the listing, i.e.\ all characters upto 'end environment'.
% We must distinguish the cases 'command fashion' and 'environment'.
% \begin{macrocode}
\def\lstenv@ProcessJ{%
\lstenv@DroppedWarning %
\lst@DontEscapeToLaTeX %
\let\lstenv@arg\@empty %
\ifx\@currenvir\lstenv@name %
\expandafter\lstenv@ProcessJEnv %
\else %
% \end{macrocode}
% The first case is pretty simple: The code is terminated by |\end|\meta{name of environment}.
% Thus we expand that control sequence before defining a temporary macro, which gets all characters upto that control sequence.
% Inside the temporary macro we assign the argument and call a submacro doing the rest.
% \begin{macrocode}
\expandafter\def\expandafter\lst@temp\expandafter##1%
\csname end\lstenv@name\endcsname{%
\lstenv@AddArg{##1}\lstenv@ProcessJ@}%
% \end{macrocode}
% Back to the definition of |\lstenv@ProcessJ| we call the temporary macro.
% \begin{macrocode}
\expandafter\lst@temp %
\fi}
% \end{macrocode}
% We must append an active backslash and the 'end string' to |\lstenv@arg|.
% So all other processing won't notice that the code has been inside an argument.
% But the EOL character is chr(10)=|^^J| now and not chr(13).
% Finally we execute |\lstenv@arg| to typeset the listing.
% Note that we need |\lccode`\A=`\A| to preserve the argument of |\lstCC@Let| --- but obviously we could also write |\lstCC@Let{10}|\ldots
% \begin{macrocode}
\begingroup \lccode`\~=`\\ \lccode`\A=`\A
\lowercase{\gdef\lstenv@ProcessJ@{%
\expandafter\lst@lAddTo\expandafter\lstenv@arg %
\expandafter{\expandafter\ \expandafter~\lstenv@endstring}%
\lstCC@Let{"000A}\lst@MProcessListing \def\lst@BOLGobble##1{}%
\expandafter\lst@BOLGobble\lstenv@arg}
}\endgroup
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstenv@ProcessJEnv}
% Here we get all characters upto an |\end| (and the following argument).
% If the following argument equals |\lstenv@name|, we have found the end of environment and start typesetting.
% \begin{macrocode}
\def\lstenv@ProcessJEnv#1\end#2{\def\lst@temp{#2}%
\ifx\lstenv@name\lst@temp %
\lstenv@AddArg{#1}%
\expandafter\lstenv@ProcessJ@ %
\else %
% \end{macrocode}
% Otherwise we append the characters including the eaten |\end| and the eaten argument to current |\lstenv@arg|.
% And we look again for the end of environment.
% \begin{macrocode}
\lstenv@AddArg{#1\\end\{#2\}}%
\expandafter\lstenv@ProcessJEnv %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{environment}{lstlisting}
% The awkward work is done, here we deal with continued line numbering.
% \lsthelper{Boris Veytsman}{boris@plmsc.psu.edu}{1998/03/25}{continue line numbering: a.c b.c a.c} proposed to continue line numbers according to listing names.
% Thus we must save the name and either make a LOL item or define the first line number.
% Note that the macro |\lstno@| will be undefined or equivalent to |\relax|, so we always start with line number 1 in case of an empty name.
% Moreover we first test if the user has forgotten the name argument.
% \begin{macrocode}
\lst@Environment{lstlisting}[2][]\is
{\lstenv@TestEOLChar{#2}%
\expandafter\ifx\csname lstno@\lst@intname\endcsname \relax %
\ifx\lst@intname\@empty\else \lst@AddToLOL{#2}{}\fi %
\else %
\edef\lst@firstline{\csname lstno@\lst@intname\endcsname}%
\let\lst@prelisting\lst@@prelisting %
\let\lst@postlisting\lst@@postlisting %
\fi %
\lstset{#1}}
% \end{macrocode}
% At the end of environment we simply save the current line number.
% If the listing name is empty, we use a space instead of the name.
% This leaves the macro |\lstno@| undefined.
% \begin{macrocode}
{\ifx\lst@intname\@empty %
\expandafter\xdef\csname lstno@ \endcsname{\the\lst@lineno}%
\else %
\expandafter\xdef\csname lstno@\lst@intname\endcsname %
{\the\lst@lineno}%
\fi}
% \end{macrocode}
% \end{environment}
%
% \begin{macro}{\lstenv@TestEOLChar}
% \begin{macro}{\lstenv@EOLCharError}
% Here we test for the two possible EOL characters.
% \begin{macrocode}
\begingroup \lccode`\~=`\^^M\lowercase{%
\gdef\lstenv@TestEOLChar#1{%
\lst@SetName{}%
\ifx~#1\lstenv@EOLCharError \else %
\ifx^^J#1\lstenv@EOLCharError \else %
\lst@SetName{#1}%
\fi %
\fi}
}\endgroup
% \end{macrocode}
% A simple error message.
% \begin{macrocode}
\def\lstenv@EOLCharError{%
\PackageError{Listings}
{Oops! It seems you've forgotten the argument to\MessageBreak %
a listing environment. Assuming empty argument}%
{Type <RETURN> to proceed.}}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{aspect}{advancelineno}
% \begin{aspect}{resetlineno}
% The last two aspects in this section simply advance/reset the first line.
% \begin{macrocode}
\lst@Aspect{advancelineno}
{\global\lst@lineno\lst@firstline\relax %
\global\advance\lst@lineno#1\relax %
\edef\lst@firstline{\the\lst@lineno}}
\lst@Aspect{resetlineno}[1]{\def\lst@firstline{#1}}
% \end{macrocode}
% \end{aspect}\end{aspect}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Inline listings}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lstinline}
% We redefine some macros here since they are possibly not save inside |\hbox|.
% Furthermore we use flexible columns and suppress \TeX\ comment lines.
% After doing initialization we redefine |\everypar| and the new line macro.
% We don't want them.
% \begin{macrocode}
\def\lstinline{\hbox\bgroup %
\let\smallbreak\relax %
\let\lst@prelisting\relax \let\lst@postlisting\relax %
\let\lst@ifflexible\iftrue \lst@DontEscapeToLaTeX %
\def\lst@firstline{1}\def\lst@lastline{1}%
\lst@Init\relax \everypar{}\global\let\lst@NewLine\relax %
\lst@IfNextCharActive\lst@InlineM\lst@InlineJ}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@InlineM}
% \begin{macro}{\lst@InlineJ}
% treat the cases of 'normal' inlines and inline listings inside an argument.
% In the first case the given character ends the inline listing and EOL (within such a listing) immediately ends it and produces an error message.
% \begin{macrocode}
\def\lst@InlineM#1{%
\lstCC@Def{`#1}{\lst@DeInit\egroup}%
\lstCC@Def{"000D}{\lst@DeInit\egroup %
\PackageError{Listings}{lstinline ended by EOL}\@ehc}}
% \end{macrocode}
% In the other case we get all characters upto |#1| (via temporary macro), make these characters active, execute (typeset) them and end the listing.
% That's all about it.
% \begin{macrocode}
\def\lst@InlineJ#1{%
\def\lst@temp##1#1{%
\let\lstenv@arg\@empty \lstenv@AddArg{##1}%
\lstenv@arg \lst@DeInit\egroup}%
\lst@temp}
% \end{macrocode}
% \end{macro}\end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{The box command}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lstbox}
% The macro opens the |\hbox| right at the beginning and indicate its usage.
% Then we adjust some \lst-parameters:
% We switch to |\lstlistingtrue| since the command is intend to be used with small listings only;
% |\smallbreak|s preceding and following each listing are removed by redefining |\smallbreak|.
% \begin{macrocode}
\newcommand\lstbox{%
\hbox\bgroup %
\let\lst@ifbox\iftrue %
\let\smallbreak\relax %
\let\lst@prelisting\relax \let\lst@postlisting\relax %
\let\lst@@prelisting\relax\let\lst@@postlisting\relax %
\lst@outerspread\z@ \lst@innerspread\z@ %
\@ifnextchar[{\lstbox@}{\lstbox@[c]}}
% \end{macrocode}
% Here we have to choose the right box --- in fact |\vcenter| isn't a box.
% \begin{macrocode}
\def\lstbox@[#1]{%
\hbox to\z@\bgroup %
$\if#1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi %
\bgroup}%
% \end{macrocode}
% We need to
% \begin{macrocode}
\let\lst@ifbox\iffalse
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@EndBox}
% And the counterpart: We have to close some groups (and use |\hss| inside the |\hbox| to $0$pt).
% The outer |\hbox| gets its correct width using a |\vrule|.
% \begin{macrocode}
\def\lst@EndBox{%
\egroup $\hss \egroup %
\vrule width\lst@maxwidth height\z@ depth\z@ %
\egroup}
% \end{macrocode}
% But that macro is called (if and) only if we've begun a |\lstbox| before.
% Note that we are possibly inside a \lst-environment here, so we have to execute |\lst@EndBox| either now or after closing the environment group.
% \begin{macrocode}
\lst@AddToHook{OnExit}
{\lst@ifbox %
\global\advance\lst@maxwidth-\lst@innerspread %
\global\advance\lst@maxwidth-\lst@outerspread %
\ifx\@currenvir\lstenv@name %
\expandafter\expandafter\expandafter\aftergroup %
\fi %
\expandafter\lst@EndBox %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@maxwidth}
% is to be allocated:
% \begin{macrocode}
\newdimen\lst@maxwidth % \global
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{InitVars}{\global\lst@maxwidth\z@}
% \end{macrocode}
% Determine width of just printed line and update |\lst@maxwidth|.
% Here we assume that all characters of the line have been output.
% \begin{macrocode}
\lst@AddToHook{InitVarsEOL}
{\@tempdima \lst@column\lst@width %
\advance\@tempdima -\lst@pos\lst@width %
\ifdim\lst@lostspace<\z@ \advance\@tempdima -\lst@lostspace \fi %
\ifdim\@tempdima>\lst@maxwidth \global\lst@maxwidth\@tempdima \fi}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \section{First \lst-aspects and related macros}
%
% In fact we've already defined some aspects, e.g.\ |language| and |style|.
%
%
% \subsection{Keywords}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{TODO}
% The internal keyword managing should be reorganised, so that is also handles the special characters $<,>,\vert,\sim$.
% \end{TODO}
% We have to decide whether or not a given character sequence is a reserved word.
% For example, if the character sequence is |key|, we define a macro
% \begin{verbatim}
% \def\lst@temp#1,key,#2\relax{...}\end{verbatim}
% Afterwards we call the macro with the following arguments:
% \begin{itemize}
% \item[] |,|all current keywords|,key,\relax|
% \end{itemize}
% The additional |,key,\relax| holds up the syntax of |\lst@temp|.
% When \TeX{} passes the arguments, the second is empty if and only if |key| is not a current keyword.
% So we know whether or not to select keyword style.
%
% Since \TeX{} always passes two arguments to |\lst@temp|, the whole 'input' |\lst@keywords,#1,\relax| is split in two parts.
% So there is no need to sort the keywords by probability.
% Alternatively you could do so and make a loop for the keyword tests, which terminates right after finding a keyword.
% You might think and guess that's faster than the \TeX{}nique used here.
% If your source code uses the three or four most common keywords only, you are right.
% In fact the very first versions 0.1 and 0.11 have used something like loops (even something faster), which in general is slower than this here.
% \begin{TODO}
% There exists a faster way.
% For each keyword we make |\lstk@|\emph{the keyword} equivalent to keyword style.
% |\csname lstk@|\emph{test word}|\endcsname| expands to |\relax| if the control sequence is undefined and to keyword style otherwise.
% That's the complete keyword test!
% It works very well, but needs more of \TeX{}'s memory.
% Therefore we should define also 'memory saving' and/or 'speeding up' option.
%
% Note: A keyword or character string in this state might contain |\lst@underscore| and |\lst@minus| (and possibly more macro names), which will expand inside |\csname|\ldots|\endcsname|.
% Hence the definition of |\lstk@|\emph{the keyword} needs some care.
% An easy trick: During keyword definition and keyword testing the macros should expand to |_| and |-|, respectively.
% But the reassignments of |_|, |-|, \ldots\ also need time, so the implemented way is possibly faster \ldots
% \end{TODO}
%
% \begin{macro}{\lst@SetStyleFor}
% |\relax| terminates the argument here since it is faster than enclosing it in braces.
% All the rest should be clear from the discussion above.
% \begin{macrocode}
\def\lst@SetStyleFor#1\relax{%
\def\lst@temp##1,#1,##2\relax{%
\ifx\@empty##2\@empty \let\lst@thestyle\lst@nonkeywordstyle %
\else \let\lst@thestyle\lst@keywordstyle\fi}%
\expandafter\lst@temp\expandafter,\lst@keywords,#1,\relax}%
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@SetStyleForNonSensitive}
% We implement a case insensitive version.
% Use of two |\uppercase|s normalize the argument.
% \begin{macrocode}
\def\lst@SetStyleForNonSensitive#1\relax{%
\uppercase{\def\lst@temp##1,#1},##2\relax{%
\ifx\@empty##2\@empty \let\lst@thestyle\lst@nonkeywordstyle %
\else \let\lst@thestyle\lst@keywordstyle\fi}%
\uppercase{%
\expandafter\lst@temp\expandafter,\lst@keywords,#1},\relax}%
% \end{macrocode}
% Note: This macro and the coming |\lst@IfOneOfNonSensitive| both assume that the keywords in |\lst@keywords| are already upper case!
% \end{macro}
%
% The code above must be activated, of course:
% We detect keywords if and only if we haven't entered a special mode (comment, string, etc.).
% \begin{macrocode}
\lst@AddToHook{Output}
{\lst@ifmode %
\let\lst@thestyle\relax %
\else %
\expandafter\lst@SetStyleFor\the\lst@token\relax %
\fi}
% \end{macrocode}
%
% \begin{macro}{\lst@IfOneOf}
% \begin{macro}{\lst@IfOneOfNonSensitive}
% These macros are very familiar with the keyword tests.
% Roughly speaking the fixed |\lst@keywords| is replaced by an arbitrary macro.
% The first argument has the same meaning and is terminated by |\relax|, whereas the second must be a macro name.
% If and only if that macro (= keyword list) contains the first argument, the third parameter is executed (and the fourth otherwise).
% \begin{macrocode}
\def\lst@IfOneOf#1\relax#2{%
\def\lst@temp##1,#1,##2\relax{%
\ifx \@empty##2\@empty \expandafter\@secondoftwo %
\else \expandafter\@firstoftwo \fi}%
\expandafter\lst@temp\expandafter,#2,#1,\relax}%
% \end{macrocode}
% \begin{macrocode}
\def\lst@IfOneOfNonSensitive#1\relax#2{%
\uppercase{\def\lst@temp##1,#1},##2\relax{%
\ifx \@empty##2\@empty \expandafter\@secondoftwo %
\else \expandafter\@firstoftwo \fi}%
\uppercase\expandafter{%
\expandafter\lst@temp\expandafter,#2,#1},\relax}%
% \end{macrocode}
% Instead of |\lst@SetStyleFor key\relax|, we could also write
% \begin{verbatim}
% \lst@IfOneOf key\relax \lst@keywords %
% {\let\lst@thestyle\lst@keywordstyle}
% {\let\lst@thestyle\lst@nonkeywordstyle}\end{verbatim}
% \end{macro}\end{macro}
%
% \begin{macro}{\lststorekeywords}
% Note that this command stores the keywords globally.
% \begin{macrocode}
\newcommand\lststorekeywords[2]{\gdef#1{#2}}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{sensitive}
% Announcement and init:
% \begin{macrocode}
\lst@Aspect{sensitive}[t]{\lstKV@SetIfKey\lst@ifsensitive{#1}}
\lst@AddToHook{SetLanguage}{\let\lst@ifsentitive\iftrue}
% \end{macrocode}
% \end{aspect}
%
% \noindent
% Now we consider the aspects getting keywords from the user.
% They work up the keywords a little bit, namely using |\lst@Make|\ldots|KeywordArg|.
%
% \begin{aspect}{keywords}
% \lsthelper{Ralf Quast}{rquast@hs.uni-hamburg.de}{1998/01/08}{name \keywords incompatible with AMS classes} reported a naming conflict with AMS classes.
% Usage of \textsf{keyval} package removes it.
% The easy definition:
% \begin{macrocode}
\lst@Aspect{keywords}
{\lst@MakeSpecKeywordArg{#1}\let\lst@keywords\lst@arg}
% \end{macrocode}
% We have to delete all current keywords before selecting a new language --- otherwise keywords from the previous language would be present if the user specifies no keywords.
% \begin{macrocode}
\lst@AddToHook{SetLanguage}{\let\lst@keywords\@empty}
% \end{macrocode}
% If the user wants case insensitive keywords, she'll get it:
% We assign the correct test macros and make all keywords upper case.
% Note that these changes are local.
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\lst@ifsensitive\else %
\let\lst@SetStyleFor\lst@SetStyleForNonSensitive %
\let\lst@IfOneOf\lst@IfOneOfNonSensitive %
\lst@MakeMacroUppercase\lst@keywords %
\fi}
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lst@MakeMacroUppercase}
% This macro makes the contents of a given macro (if present) upper case.
% \begin{macrocode}
\def\lst@MakeMacroUppercase#1{%
\ifx#1\@undefined\else \uppercase\expandafter{%
\expandafter\def\expandafter#1\expandafter{#1}}%
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{morekeywords}
% Add keywords or append control sequence with argument:
% \begin{macrocode}
\lst@Aspect{morekeywords}
{\lst@MakeMoreSpecKeywordArg{,#1}%
\expandafter\lst@lAddTo\expandafter\lst@keywords %
\expandafter{\lst@arg}}
% \end{macrocode}
% \end{aspect}
%
% \begin{aspect}{deletekeywords}
% The 'submacro' |\lst@DeleteKeysIn| has been defined in section \ref{iReplacingCharacters}.
% \begin{macrocode}
\lst@Aspect{deletekeywords}
{\lst@MakeKeywordArg{#1}%
\lst@DeleteKeysIn\lst@keywords\lst@arg}
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lst@MakeKeywordArg}
% \begin{macro}{\lst@MakeSpecKeywordArg}
% \begin{macro}{\lst@MakeMoreSpecKeywordArg}
% The keyword commands don't save their parameters as they are.
% All spaces are removed and underscores, dollars and minuses are replaced by |\lst@underscore|, |\lst@dollar| and |\lst@minus|.
% The first thing prepares keyword tests and the second the output.
% The macro |\lst@arg| holds the parameter free of spaces, underscores and minuses.
% Use of |\zap@space| was proposed by \lsthelper{Rolf Niepraschk}{NIEPRASCHK@PTB.DE}{1997/04/24}{use \zap@space}.
% \begin{macrocode}
\def\lst@MakeKeywordArg#1{\edef\lst@arg{\zap@space#1 \@empty}%
\lst@ReplaceIn\lst@arg{_\lst@underscore $\lst@dollar -\lst@minus}}
% \end{macrocode}
% The following two macros also scan for special characters like \#, $<$ and $>$.
% \begin{macrocode}
\def\lst@MakeSpecKeywordArg{%
\let\lst@ialsodigit\@empty \let\lst@ialsoletter\@empty %
\lst@MakeMoreSpecKeywordArg}
% \end{macrocode}
% \begin{macrocode}
\def\lst@MakeMoreSpecKeywordArg#1{\edef\lst@arg{\zap@space#1 \@empty}%
\lstCC@lettertrue %
\expandafter\lst@SpecialKeywordScan\lst@arg\relax %
\lst@ReplaceIn\lst@arg{_\lst@underscore $\lst@dollar -\lst@minus}}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lst@SpecialKeywordScan}
% How does this scan work?
% Whenever we encounter a non-letter or non-digit in a keyword, we call |\lst@SKSAdd| to store that character.
% If we reach the end of keyword list, we terminate the loop by gobbling one token after the latest |\fi|.
% \begin{macrocode}
\def\lst@SpecialKeywordScan#1{%
\ifx\relax#1%
\expandafter\@gobble %
\else %
% \end{macrocode}
% If the current character is a comma, the next character must be (or become) a letter since it starts a keyword.
% This switch is turned false after reading the next character.
% \begin{macrocode}
\ifx,#1%
\lstCC@lettertrue %
\else %
\ifnum`#1<"40\relax %
\ifnum`#1<"30\relax \lst@SKSAdd#1\else %
\ifnum`#1>"39\relax \lst@SKSAdd#1\else %
% \end{macrocode}
% If we've found a digit, we do a special test to decide whether the digit becomes a letter or not.
% \begin{macrocode}
\lst@SKS@#1%
\fi \fi %
\else %
\ifnum`#1<"5B\relax \else %
\ifnum`#1="5F\relax \else %
\ifnum`#1<"61\relax \lst@SKSAdd#1\else %
\ifnum`#1<"7B\relax \else %
\ifnum`#1<"80\relax \lst@SKSAdd#1 %
\fi \fi \fi \fi \fi %
\fi %
\lstCC@letterfalse %
\fi %
\fi \lst@SpecialKeywordScan}
% \end{macrocode}
% The special test for digits: Since any digit is already a digit it needs only to become a letter if necessary.
% \begin{macrocode}
\def\lst@SKS@#1{\lstCC@ifletter \lst@SKSAdd#1\fi}
% \end{macrocode}
% The macros |\lst@ialsoletter| and |\lst@ialsodigit| contain the characters.
% If not already contained in the appropiate macro, we append the character.
% Refer |\lst@SelectStyleFor| how we scan for a substring (of length 1).
% \begin{macrocode}
\def\lst@SKSAdd#1{%
\lstCC@ifletter %
\def\lst@temp##1#1##2\relax{%
\ifx\@empty##2\@empty %
\lst@lAddTo\lst@ialsoletter{#1}%
\fi}%
\expandafter\lst@temp\lst@ialsoletter#1\relax %
\else %
\def\lst@temp##1#1##2\relax{%
\ifx\@empty##2\@empty %
\lst@lAddTo\lst@ialsodigit{#1}%
\fi}%
\expandafter\lst@temp\lst@ialsodigit#1\relax %
\fi}
% \end{macrocode}
% \begin{macrocode}
\let\lst@ialsoletter\@empty \let\lst@ialsodigit\@empty % init
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{alsoletter}
% \begin{aspect}{alsodigit}
% \begin{aspect}{alsoother}
% For now three easy definitions --- easy since I don't explain the last hook.
% \begin{macrocode}
\lst@Aspect{alsoletter}{\def\lst@alsoletter{#1}}
\lst@Aspect{alsodigit}{\def\lst@alsodigit{#1}}
\lst@Aspect{alsoother}{\def\lst@alsoother{#1}}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{SetLanguage}
{\let\lst@alsoletter\@empty %
\let\lst@alsodigit\@empty %
\let\lst@alsoother\@empty}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{SelectCharTable}
{\lstCC@ChangeBasicClass\lstCC@ProcessOther\lst@alsoother %
\lstCC@ChangeBasicClass\lstCC@ProcessDigit\lst@ialsodigit %
\lstCC@ChangeBasicClass\lstCC@ProcessDigit\lst@alsodigit %
\lstCC@ChangeBasicClass\lstCC@ProcessLetter\lst@ialsoletter %
\lstCC@ChangeBasicClass\lstCC@ProcessLetter\lst@alsoletter}
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}
%
% \begin{macro}{\lst@minus}
% What is the |\ifx|\ldots{} in |\lst@minus| good for?
% If you use typewriter fonts, it ensures that |----| is typeset |----| and not $-$$-$$-$$-$ as in version 0.17.
% Bug encountered by \lsthelper{Dr. Jobst Hoffmann}{HOFFMANN@rz.rwth-aachen.de}{1998/03/30}{\lst@minus\ and typewriter fonts}.
% \begin{macrocode}
\def\lst@minus{\ifx\f@family\ttdefault-{}\else$-$\fi}
\def\lst@dollar{\ifx\f@family\ttdefault\textdollar\else\textdollar\fi}
\def\lst@asterisk{\ifx\f@family\ttdefault*\else\textasteriskcentered\fi}
\def\lst@less{\ifx\f@family\ttdefault<\else\textless\fi}
\def\lst@greater{\ifx\f@family\ttdefault>\else\textgreater\fi}
\def\lst@backslash{\ifx\f@family\ttdefault\char92\else\textbackslash\fi}
\def\lst@underscore{%
\ifx\f@family\ttdefault\char95\else\textunderscore\fi}
\def\lst@lbrace{\ifx\f@family\ttdefault\char123\else\textbraceleft\fi}
\def\lst@bar{\ifx\f@family\ttdefault|\else\textbar\fi}
\def\lst@rbrace{\ifx\f@family\ttdefault\char125\else\textbraceright\fi}
% \end{macrocode}
% |\ttdefault| is defined |\long|, so the |\ifx| doesn't work since |\f@family| isn't defined |\long|!
% We go around this problem by redefining |\ttdefault| locally:
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}{\edef\ttdefault{\ttdefault}}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{basicstyle}
% \begin{aspect}{keywordstyle}
% \begin{aspect}{nonkeywordstyle}
% We shouldn't forget these style aspects.
% \begin{macrocode}
\lst@Aspect{basicstyle}{\def\lst@basicstyle{#1}}
\lst@Aspect{keywordstyle}{\def\lst@keywordstyle{#1}}
\lst@Aspect{nonkeywordstyle}{\def\lst@nonkeywordstyle{#1}}
% \end{macrocode}
% \lsthelper{Anders Edenbrandt}{Anders.Edenbrandt@dna.lth.se}{1997/04/22}{preload of .fd files} found a bug with \texttt{.fd} files.
% Here's my solution: Since we will change catcodes, these files can't be read on demand --- it would yield to obscure error messages.
% The |\setbox| sequence ensures (most times) that they are read before.
% We simply typeset distinct characters from each \texttt{.fd} file.
% Note: We never output that box.
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\lst@basicstyle %
\setbox\@tempboxa\hbox{\lst@loadfd %
{\lst@keywordstyle \lst@loadfd}%
{\lst@nonkeywordstyle \lst@loadfd}}}
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}
%
% \begin{macro}{\lst@loadfd}
% These are hopefully all necessary characters.
% \begin{macrocode}
\def\lst@loadfd{a0\lst@asterisk\lst@less}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{ndkeywords}
% \begin{aspect}{ndkeywordstyle}
% \begin{aspect}{morendkeywords}
% \begin{aspect}{deletendkeywords}
% We define a second keyword class in the same manner if the user wants it.
% \begin{macrocode}
\@ifundefined{lst@ndkeywords}{}{%
\let\lst@ndkeywords\@empty \let\lst@ndkeywordstyle\@empty % init
\lst@Aspect{ndkeywords}
{\lst@MakeSpecKeywordArg{#1}\let\lst@ndkeywords\lst@arg}
\lst@AddToHook{SetLanguage}{\let\lst@ndkeywords\@empty}
\lst@AddToHook{BeforeSelectCharTable}
{\lst@ifsensitive\else %
\lst@MakeMacroUppercase\lst@ndkeywords %
\fi}
% \end{macrocode}
% \begin{macrocode}
\lst@Aspect{ndkeywordstyle}{\def\lst@ndkeywordstyle{#1}}
\lst@AddToHook{BeforeSelectCharTable}
{\setbox\@tempboxa\hbox{{\lst@ndkeywordstyle \lst@loadfd}}}
% \end{macrocode}
% \begin{macrocode}
\lst@Aspect{morendkeywords}
{\lst@MakeMoreSpecKeywordArg{,#1}%
\expandafter\lst@lAddTo\expandafter\lst@ndkeywords %
\expandafter{\lst@arg}}
% \end{macrocode}
% \begin{macrocode}
\lst@Aspect{deletendkeywords}
{\lst@MakeKeywordArg{#1}%
\lst@DeleteKeysIn\lst@ndkeywords\lst@arg}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{Output}
{\lst@ifmode\else %
\expandafter\lst@IfOneOf\the\lst@token\relax \lst@ndkeywords %
{\let\lst@thestyle\lst@ndkeywordstyle}{}%
\fi}
% \end{macrocode}
% Finally we end the argument from |\@ifundefined|.
% \begin{macrocode}
}
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}\end{aspect}
%
% \begin{aspect}{rdkeywords}
% \begin{aspect}{rdkeywordstyle}
% \begin{aspect}{morerdkeywords}
% \begin{aspect}{deleterdkeywords}
% That's the power of \lst-aspects: An optional third keyword class.
% \begin{macrocode}
\@ifundefined{lst@rdkeywords}{}{%
\let\lst@rdkeywords\@empty \let\lst@rdkeywordstyle\@empty % init
\lst@Aspect{rdkeywords}
{\lst@MakeSpecKeywordArg{#1}\let\lst@rdkeywords\lst@arg}
\lst@AddToHook{SetLanguage}{\let\lst@rdkeywords\@empty}
\lst@AddToHook{BeforeSelectCharTable}
{\lst@ifsensitive\else %
\lst@MakeMacroUppercase\lst@rdkeywords %
\fi}
% \end{macrocode}
% \begin{macrocode}
\lst@Aspect{rdkeywordstyle}{\def\lst@rdkeywordstyle{#1}}
\lst@AddToHook{BeforeSelectCharTable}
{\setbox\@tempboxa\hbox{{\lst@rdkeywordstyle \lst@loadfd}}}
% \end{macrocode}
% \begin{macrocode}
\lst@Aspect{morerdkeywords}
{\lst@MakeMoreSpecKeywordArg{,#1}%
\expandafter\lst@lAddTo\expandafter\lst@rdkeywords %
\expandafter{\lst@arg}}
% \end{macrocode}
% \begin{macrocode}
\lst@Aspect{deleterdkeywords}
{\lst@MakeKeywordArg{#1}%
\lst@DeleteKeysIn\lst@rdkeywords\lst@arg}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{Output}
{\lst@ifmode\else %
\expandafter\lst@IfOneOf\the\lst@token\relax \lst@rdkeywords %
{\let\lst@thestyle\lst@rdkeywordstyle}{}%
\fi}
}
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}\end{aspect}
%
%
% \subsection{Export of indentifiers}
%
% \begin{aspect}{index}
% We implement this aspect in the same manner.
% \begin{macrocode}
\@ifundefined{lst@index}{}{%
\lst@Aspect{index}{\lst@MakeSpecKeywordArg{#1}\let\lst@index\lst@arg}
\lst@AddToHook{BeforeSelectCharTable}
{\lst@ifsensitive\else %
\lst@MakeMacroUppercase\lst@index %
\fi}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{Output}
{\lst@ifmode\else %
\expandafter\lst@IfOneOf\the\lst@token\relax \lst@index %
{\expandafter\lst@indexmacro\expandafter{\the\lst@token}}{}%
\fi}
% \end{macrocode}
% \begin{macrocode}
\lst@Aspect{indexmacro}{\let\lst@indexmacro#1}
\newcommand\lstindexmacro[1]{\index{{\ttfamily#1}}}
\let\lst@index\@empty \let\lst@indexmacro\lstindexmacro % init
}
% \end{macrocode}
% \end{aspect}
%
% \begin{aspect}{procnamestyle}
% \begin{aspect}{prockeywords}
% \begin{aspect}{indexprocnames}
% The 'idea' here is the usage of a global |\lst@ifprocname| indicating a preceding 'procedure keyword'.
% All the other is known stuff.
% \begin{macrocode}
\@ifundefined{lst@prockeywords}{}{%
\lst@Aspect{prockeywords}{%
\lst@MakeSpecKeywordArg{#1}\let\lst@prockeywords\lst@arg}
\lst@Aspect{procnamestyle}{\def\lst@procnamestyle{#1}}
\lst@Aspect{indexprocnames}[t]{\lstKV@SetIfKey\lst@ifindexproc{#1}}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\setbox\@tempboxa\hbox{\lst@procnamestyle\lst@loadfd}%
\lst@ifsensitive\else %
\lst@MakeMacroUppercase\lst@prockeywords %
\fi %
\lst@ifindexproc \ifx\lst@indexmacro\@undefined %
\let\lst@indexmacro\@gobble %
\fi \fi}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{Output}
{\lst@ifmode\else %
\lst@ifprocname %
\let\lst@thestyle\lst@procnamestyle %
\expandafter\lst@indexmacro\expandafter{\the\lst@token}%
\lst@procnamefalse %
\else \expandafter%
\lst@IfOneOf\the\lst@token\relax \lst@prockeywords %
{\lst@procnametrue}{}%
\fi %
\fi}
% \end{macrocode}
% \begin{macrocode}
\def\lst@procnametrue{\global\let\lst@ifprocname\iftrue}
\def\lst@procnamefalse{\global\let\lst@ifprocname\iffalse}
% \end{macrocode}
% \begin{macrocode}
\let\lst@prockeywords\@empty % init
\lstset{procnamestyle={},indexprocnames=false}% init
\lst@procnamefalse % init
}
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Labels}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \lsthelper{Rolf Niepraschk}{NIEPRASCHK@PTB.DE}{1997/04/24}{labels} asked for this feature.
%
% \begin{aspect}{labelstyle}
% \begin{aspect}{labelsep}
% \begin{aspect}{labelstep}
% The usual stuff:
% Definition with check for legal step count, \ldots
% \begin{macrocode}
\lst@Aspect{labelstyle}{\def\lst@labelstyle{#1}}
\lst@Aspect{labelsep}{\def\lst@labelsep{#1}}
\lst@Aspect{labelstep}%
{\ifnum #1>\m@ne %
\def\lst@labelstep{#1}%
\else %
\PackageError{Listings}{Nonnegative integer expected}%
{You can't use `#1' as step count for labels.^^J%
I'll forget it and proceed.}%
\fi}
% \end{macrocode}
% and load of \texttt{.fd} files (if necessary).
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\setbox\@tempboxa\hbox{\lst@stringstyle \lst@loadfd}}
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}
%
% \begin{macro}{\lst@skiplabels}
% But there are more things to do.
% \begin{macrocode}
\newcount\lst@skiplabels % \global
% \end{macrocode}
% We calculate how many lines must skip their label.
% The formula is
% $$|\lst@skiplabels|=
% \textrm{\emph{first printing line}}\bmod|\lst@labelstep|.$$
% Note that we use a nonpositive representative for |\lst@skiplabels|.
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\ifnum\lst@labelstep>\z@ %
\global\lst@skiplabels\lst@firstline\relax %
\global\divide\lst@skiplabels\lst@labelstep %
\global\multiply\lst@skiplabels-\lst@labelstep %
\global\advance\lst@skiplabels\lst@firstline\relax %
\ifnum\lst@skiplabels>\z@ %
\global\advance\lst@skiplabels -\lst@labelstep\relax %
\fi %
% \end{macrocode}
% If |\lst@labelstep| is nonpositive (in fact zero), no labels are printed:
% \begin{macrocode}
\else %
\let\lst@SkipOrPrintLabel\relax %
\fi}
\lst@AddToHook{EveryLine}{\lst@SkipOrPrintLabel}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@SkipOrPrintLabel}
% But default is this.
% We use the fact that |\lst@skiplabels| is nonpositive.
% The counter advances every line and if that counter is zero, we print a line number and decrement the counter by |\lst@labelstep|.
% \begin{macrocode}
\def\lst@SkipOrPrintLabel{%
\ifnum\lst@skiplabels=\z@ %
\global\advance\lst@skiplabels-\lst@labelstep\relax %
\llap{\lst@labelstyle{\the\lst@lineno}\kern\lst@labelsep}%
\fi %
\global\advance\lst@skiplabels\@ne}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Parshape and lineskip}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@innerspread}
% \begin{macro}{\lst@outerspread}
% Just allocate these dimensions.
% \begin{macrocode}
\newdimen\lst@innerspread \newdimen\lst@outerspread
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{aspect}{wholeline}
% \begin{aspect}{indent}
% \begin{aspect}{spread}
% Usual stuff.
% \begin{macrocode}
\lst@Aspect{wholeline}[t]{\lstKV@SetIfKey\lst@ifwholeline{#1}}
\lst@Aspect{indent}{\def\lst@indent{#1}}
\lst@Aspect{spread}{\lstspread@#1,,\relax}
% \end{macrocode}
% \lsthelper{Harald Haders}{h.haders@tu-bs.de}{1998/03/30}{inner- and outerspread} had the idea of two spreads (inner and outer).
% We either divide the dimension by two or assign the two dimensions to inner- and outerspread.
% \begin{macrocode}
\def\lstspread@#1,#2,#3\relax{%
\lst@innerspread#1\relax %
\ifx\@empty#2\@empty %
\divide\lst@innerspread\tw@\relax %
\lst@outerspread\lst@innerspread %
\else %
\lst@outerspread#2\relax %
\fi}
% \end{macrocode}
% \begin{macrocode}
\lstset{wholeline=false,indent=\z@,spread=\z@}% init
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}
%
% \begin{macro}{\lst@parshape}
% The definition itself is easy.
% Note that we use this parshape every line (in fact every paragraph).
% Furthermore we must repeat the parshape if we close a group level --- or the shape is forgotten.
% \begin{macrocode}
\def\lst@parshape{%
\parshape\@ne %
\ifodd\c@page -\lst@innerspread\else -\lst@outerspread\fi %
\linewidth}
\lst@AddToHookAtTop{EveryLine}{\lst@parshape}
\lst@AddToHookAtTop{EndGroup}{\lst@parshape}
% \end{macrocode}
% We calculate the line width and (inner/outer) indent for a listing.
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\advance\linewidth\lst@innerspread %
\advance\linewidth\lst@outerspread %
\advance\linewidth-\lst@indent\relax %
\advance\lst@innerspread-\lst@indent\relax %
\advance\lst@outerspread-\lst@indent\relax %
\lst@ifwholeline %
\advance\linewidth\@totalleftmargin %
\else %
\advance\lst@innerspread-\@totalleftmargin %
\advance\lst@outerspread-\@totalleftmargin %
\fi %
\if@twoside\else \lst@outerspread\lst@innerspread \fi}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{lineskip}
% Finally we come to this attribute --- the introduction is due to communication with \lsthelper{Andreas Bartelt}{Andreas.Bartelt@Informatik.Uni-Oldenburg.DE}{1997/09/11}{problem with redefed \parskip; \lstlineskip introduced}.
% \begin{macrocode}
\lst@Aspect{lineskip}{\def\lst@lineskip{#1}}
\lst@AddToHook{BeforeSelectCharTable}{\parskip\lst@lineskip\relax}
\lstset{lineskip=\z@}% init
% \end{macrocode}
% \end{aspect}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Frames}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
%
% \begin{aspect}{framerulewidth}
% \begin{aspect}{framerulesep}
% \begin{aspect}{frametextsep}
% We only have to store the arguments.
% \begin{macrocode}
\lst@Aspect{framerulewidth}{\def\lst@framewidth{#1}}
\lst@Aspect{framerulesep}{\def\lst@framesep{#1}}
\lst@Aspect{frametextsep}{\def\lst@frametextsep{#1}}
% \end{macrocode}
% \begin{macrocode}
\lstset{framerulewidth=.4pt,framerulesep=2pt,frametextsep=3pt}% init
% \end{macrocode}
% \end{aspect}\end{aspect}\end{aspect}
%
% \begin{aspect}{frame}
% The main aspect saves the argument, resets all supported types |tlrbTLRB| to |\relax| and defines the user specified frame.
% \begin{macrocode}
\lst@Aspect{frame}
{\def\lst@frame{#1}%
\lstframe@\relax tlrbTLRB\relax %
\lstframe@\@empty#1\relax}
% \end{macrocode}
% This submacro defines the macros to be equivalent to |#1| (which is |\relax| or |\@empty|).
% The second argument is the list of characters terminated by |\relax|.
% \begin{macrocode}
\def\lstframe@#1#2{%
\ifx\relax#2\else %
\expandafter\let\csname lstf@#2\endcsname#1%
\expandafter\lstframe@\expandafter#1%
\fi}
% \end{macrocode}
% \begin{macrocode}
\lstset{frame={}}% init
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lst@framev}
% \begin{macro}{\lst@frameV}
% These macros typeset one or two vertical rules:
% \begin{macrocode}
\def\lst@framev{\hbox{\strut\vrule width\lst@framewidth}}
\def\lst@frameV{\hbox{\strut %
\vrule width\lst@framewidth\kern\lst@framesep %
\vrule width\lst@framewidth}}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@framelr}
% We typeset left and right frame rule every line (if not made |\relax|).
% Note that |\lst@framel| is possibly redefined and thus equivalent to |\lst@frameL|.
% \begin{macrocode}
\lst@AddToHook{EveryLine}{\lst@framelr}
\def\lst@framelr{%
\llap{\lst@framel\kern\lst@indent\kern\lst@frametextsep}%
\rlap{\kern\linewidth\kern\lst@frametextsep\lst@framer}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@frameh}
% This is the main macro for horizontal lines.
% The first parameter gives the size of the left and right corner.
% The other two parameters typeset these corners (and get the size parameter).
% Now: We move to the correct horizontal position, set the left corner, the horizontal line and the right corner.
% \begin{macrocode}
\def\lst@frameh#1#2#3{%
\hbox to\z@{%
\kern\ifodd\c@page -\lst@innerspread\else -\lst@outerspread\fi %
\kern-\lst@indent %
% \end{macrocode}
% \begin{macrocode}
\kern-\lst@frametextsep %
\ifx\lstf@L\@empty %
\llap{#2#1}%
\else \ifx\lstf@l\@empty %
\llap{#20}%
\fi \fi %
\vrule\@width\lst@frametextsep %
% \end{macrocode}
% \begin{macrocode}
\vrule\@width\lst@indent %
\vrule\@width\linewidth\@height\lst@framewidth %
% \end{macrocode}
% \begin{macrocode}
\vrule\@width\lst@frametextsep %
\ifx\lstf@R\@empty %
\rlap{#3#1}%
\else \ifx\lstf@r\@empty %
\rlap{#30}%
\fi \fi %
\hss}}
% \end{macrocode}
% Note: There are no paramaters with numbers 20 and 30.
% It's |#2| respectively |#3| with size argument 0.
% \end{macro}
%
% \begin{macro}{\lst@framet}
% \begin{macro}{\lst@frameb}
% \begin{macro}{\lst@frameT}
% \begin{macro}{\lst@frameB}
% Now we can derive the 'top' and 'bottom' frame macros quite easily:
% \begin{macrocode}
\def\lst@framet{\lst@frameh0\lst@frameTL\lst@frameTR}%
\let\lst@frameb\lst@framet
\def\lst@frameT{%
\lst@frameh1\lst@frameTL\lst@frameTR %
\vskip\lst@framesep %
\lst@frameh0\lst@frameTL\lst@frameTR}
\def\lst@frameB{%
\lst@frameh0\lst@frameBL\lst@frameBR %
\vskip\lst@framesep %
\lst@frameh1\lst@frameBL\lst@frameBR}
% \end{macrocode}
% These macros are executed where needed.
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\ifx\lstf@T\@empty %
\offinterlineskip\par\noindent\lst@frameT %
\else \ifx\lstf@t\@empty %
\offinterlineskip\par\noindent\lst@framet %
\else %
\let\lst@framet\relax %
\fi \fi %
% \end{macrocode}
% \begin{TODO}
% Replace |\offinterlineskip| by |\nointerlineskip|?
% \end{TODO}
% We look which frame types we have on the left and on the right.
% \begin{macrocode}
\let\lst@framel\relax \let\lst@framer\relax %
\ifx\lstf@L\@empty %
\let\lst@framel\lst@frameV %
\else %
\ifx\lstf@l\relax\else \let\lst@framel\lst@framev \fi %
\fi %
\ifx\lstf@R\@empty %
\let\lst@framer\lst@frameV %
\else %
\ifx\lstf@r\relax\else \let\lst@framer\lst@framev \fi %
\fi %
% \end{macrocode}
% We can speed up things if there are no vertical frames.
% \begin{macrocode}
\ifx\lst@framel\relax \ifx\lst@framer\relax %
\let\lst@framelr\relax %
\fi \fi %
% \end{macrocode}
% Finally we close the space between the horizontal rule and the first line (the 'depth' of the current line).
% \begin{macrocode}
\ifx\lst@framelr\relax\else \ifx\lst@framet\relax\else %
{\setbox\strutbox\hbox{%
\vrule\@height0pt\@depth.3\normalbaselineskip\@width\z@}%
\kern\ifodd\c@page-\lst@innerspread\else-\lst@outerspread\fi %
\lst@framelr}%
\fi \fi}
% \end{macrocode}
% The frame at the bottom:
% \begin{macrocode}
\lst@AddToHook{ExitVars}
{\ifx\lstf@B\@empty %
\offinterlineskip\everypar{}\par\noindent\lst@frameB %
\else \ifx\lstf@b\@empty %
\offinterlineskip\everypar{}\par\noindent\lst@framet %
\fi \fi}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lst@frameTL}
% \begin{macro}{\lst@frameTR}
% \begin{macro}{\lst@frameBL}
% \begin{macro}{\lst@frameBR}
% The 'corner' macros are left.
% All save the vertical rule in a temporary box to zero the depth or height of that box.
% Then we typeset the vertical and horizontal rule (in reversed order).
% \begin{macrocode}
\def\lst@frameTL#1{%
\@tempdima\lst@framesep \advance\@tempdima\lst@framewidth %
\multiply\@tempdima#1\relax %
\setbox\@tempboxa\hbox to\z@{%
\vrule\@width\lst@framewidth\@height\z@\@depth\@tempdima\hss}%
\dp\@tempboxa\z@ %
\advance\@tempdima\lst@framewidth %
\box\@tempboxa \vrule\@width\@tempdima\@height\lst@framewidth}
% \end{macrocode}
% \begin{macrocode}
\def\lst@frameTR#1{%
\@tempdima\lst@framesep \advance\@tempdima\lst@framewidth %
\multiply\@tempdima#1\relax %
\setbox\@tempboxa\hbox to\z@{\hss %
\vrule\@width\lst@framewidth\@height\z@\@depth\@tempdima}%
\dp\@tempboxa\z@ %
\advance\@tempdima\lst@framewidth %
\vrule\@width\@tempdima\@height\lst@framewidth \box\@tempboxa}
% \end{macrocode}
% \begin{macrocode}
\def\lst@frameBL#1{%
\@tempdima\lst@framesep \advance\@tempdima\lst@framewidth %
\multiply\@tempdima#1\relax %
\advance\@tempdima\lst@framewidth %
\setbox\@tempboxa\hbox to\z@{%
\vrule\@width\lst@framewidth\@height\@tempdima\hss}%
\ht\@tempboxa\z@ %
\box\@tempboxa \vrule\@width\@tempdima\@height\lst@framewidth}
% \end{macrocode}
% \begin{macrocode}
\def\lst@frameBR#1{%
\@tempdima\lst@framesep \advance\@tempdima\lst@framewidth %
\multiply\@tempdima#1\relax %
\advance\@tempdima\lst@framewidth %
\setbox\@tempboxa\hbox to\z@{\hss %
\vrule\@width\lst@framewidth\@height\@tempdima}%
\ht\@tempboxa\z@ %
\vrule\@width\@tempdima\@height\lst@framewidth \box\@tempboxa}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}\end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Pre and post listing}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{aspect}{pre}
% \begin{aspect}{post}
% A rather trivial section.
% \begin{macrocode}
\lst@Aspect{pre}{\lstKV@OptArg\lstpre@[]{#1}}
\lst@Aspect{post}{\lstKV@OptArg\lstpost@[]{#1}}
% \end{macrocode}
% \begin{macrocode}
\def\lstpre@[#1]#2{%
\def\lst@prelisting{#2}\def\lst@@prelisting{#1}}
\def\lstpost@[#1]#2{%
\def\lst@postlisting{#2}\def\lst@@postlisting{#1}}
% \end{macrocode}
% \begin{macrocode}
\lstset{pre={},post={}}% init
% \end{macrocode}
% \end{aspect}\end{aspect}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{\TeX\ comment lines}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% Communication with \lsthelper{J\"orn Wilms}{wilms@rocinante.colorado.edu}{1997/07/07}{\TeX\ comments} is responsible for this feature.
% Some characters have a special functionality in \TeX{}, e.g.\ the underbar or the dollar sign.
% These meanings are unwanted while typesetting normal source code, i.e.\ we have to define our own character table.
% But for the comment lines we must interrupt the current processing and switch back to the original meanings.
% And at the end we must restore all previous things.
%
% \begin{aspect}{texcl}
% Announcing the aspect:
% \begin{macrocode}
\lst@Aspect{texcl}[t]{\lstKV@SetIfKey\lst@iftexcl{#1}}
\lstset{texcl=false}% init
% \end{macrocode}
% Things at EOL are easy, but we must allocate new modes for (\TeX) comment lines first.
% \begin{macrocode}
\lst@NewMode\lst@TeXCLmode
\lst@NewMode\lst@CLmode
\lst@AddToHook{EOL}
{\ifnum\lst@mode=\lst@TeXCLmode %
\lst@LeaveAllModes \lst@ReenterModes %
\fi %
\ifnum\lst@mode=\lst@CLmode \lst@LeaveMode \fi}
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lstCC@BeginCommentLine}
% \begin{macro}{\lstCC@@BeginCommentLine}
% The first macro starts comment lines indicated by a single character (like |%| in \TeX), whereas the second does this for comment lines indicated by two characters (like |//| in C++).
% According to the macro naming these two macros belong more or less to section \ref{iCharacterClasses}.
% But we present them here because of \TeX\ comment lines.
%
% We print preceding characters (if any), begin the comment and output the comment separator.
% \begin{macrocode}
\def\lstCC@BeginCommentLine#1{%
\lst@NewLine \lst@PrintToken %
\lst@EnterMode{\lst@CLmode}{\lst@modetrue\lst@commentstyle}%
#1\relax %
% \end{macrocode}
% If the user don't want \TeX\ comment lines, there is nothing more to do.
% Otherwise we have to print the comment separator and interrupt the normal processing.
% \begin{macrocode}
\lst@iftexcl %
\lst@PrintToken %
\lst@LeaveMode \lst@InterruptModes %
\lst@EnterMode{\lst@TeXCLmode}{\lst@modetrue\lst@commentstyle}%
\fi}
% \end{macrocode}
% Now comes the same, but we process a 'two character'-separator.
% \begin{macrocode}
\def\lstCC@@BeginCommentLine#1#2{%
\lst@NewLine \lst@PrintToken %
\lst@EnterMode{\lst@CLmode}{\lst@modetrue\lst@commentstyle}%
#1\relax#2\relax %
\lst@iftexcl %
\lst@PrintToken %
\lst@LeaveMode \lst@InterruptModes %
\lst@EnterMode{\lst@TeXCLmode}{\lst@modetrue\lst@commentstyle}%
\fi}
% \end{macrocode}
% \end{macro}\end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \section{Doing output}
%
%
% \subsection{Output aspects and helpers}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{aspect}{flexiblecolumns}
% Do you have any idea what to write here?
% \begin{macrocode}
\lst@Aspect{flexiblecolumns}[t]{\lstKV@SetIfKey\lst@ifflexible{#1}}
\lstset{flexiblecolumns=false}% init
% \end{macrocode}
% We assign the correct output macros defined below.
% As you can see there are three main macros, which handle letters, all other printing characters and tabulator stops.
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\lst@ifflexible %
\let\lst@Output\lst@OutputFlexible %
\let\lst@OutputOther\lst@OutputOtherFlexible %
\let\lst@GotoTabStop\lst@GotoTabStopFlexible %
\fi}
% \end{macrocode}
% \end{aspect}
%
% \begin{aspect}{baseem}
% We look whether or not the user gives two numbers, i.e.\ we test for a comma.
% \begin{macrocode}
\lst@Aspect{baseem}{\lstbaseem@#1,,\relax}
% \end{macrocode}
% Here we check for legal arguments \ldots
% \begin{macrocode}
\def\lstbaseem@#1,#2,#3\relax{%
\def\lst@next{\PackageError{Listings}%
{Nonnegative number(s) expected}%
{Separate one or two such numbers by a comma, next time.^^J%
Now type <RETURN> to proceed.}}%
\ifdim #1em<\z@\else %
\def\lst@baseemfixed{#1}%
\let\lst@baseemflexible\lst@baseemfixed %
% \end{macrocode}
% and do the comma test.
% \begin{macrocode}
\ifx\@empty#2\@empty %
\let\lst@next\relax %
\else \ifdim #2em<\z@\else %
\def\lst@baseemflexible{#2}%
\let\lst@next\relax %
\fi \fi %
\fi \lst@next}
% \end{macrocode}
% \begin{macrocode}
\lstset{baseem={0.6,0.45}}% init
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lst@width}
% The dimension holds the width of a single character box while typesetting a listing.
% \begin{macrocode}
\newdimen\lst@width
\lst@AddToHook{InitVars}
{\lst@width=\lst@ifflexible\lst@baseemflexible %
\else\lst@baseemfixed\fi em\relax}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{tabsize}
% We check for a legal argument before saving it.
% \begin{macrocode}
\lst@Aspect{tabsize}
{\ifnum#1>\z@ %
\def\lst@tabsize{#1}%
\else %
\PackageError{Listings}{Strict positive integer expected}
{You can't use `#1' as tabulator length.^^J%
Type <RETURN> to forget it and to proceed.}%
\fi}
% \end{macrocode}
% Default tabsize is 8 as proposed by \lsthelper{Rolf Niepraschk}{NIEPRASCHK@PTB.DE}{1997/04/24}{tabsize=8}.
% \begin{macrocode}
\lstset{tabsize=8}% init
% \end{macrocode}
% \end{aspect}
%
% Before looking at the output macros, we have to introduce some registers.
%
% \begin{macro}{\lst@token}
% \begin{macro}{\lst@length}
% The token register contains the current character string, for example |char| if we have just read these characters and a whitespace before.
% The counter |\lst@length| holds the length of the string and that's 4 in the example.
% \begin{macrocode}
\newtoks\lst@token \newcount\lst@length
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{InitVarsEOL}{\lst@token{}\lst@length\z@}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@lastother}
% This is not a \TeX{} register.
% This macro is equivalent to the last 'other' character, other in the sense of section \ref{iCharacterClasses}.
% \begin{macrocode}
\lst@AddToHook{InitVarsEOL}{\let\lst@lastother\@empty}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@column}
% \begin{macro}{\lst@pos}
% With the two counters it is possible to determine the current column.
% It's the sum of |\lst@column| and |\lst@length| plus one minus |\lst@pos| --- |\lst@pos| will be nonpositive.
% It seems to be troublesome to decide whether a new line has just begun or not, i.e.\ if the current column number is one.
% And that's true.
% \begin{macrocode}
\newcount\lst@column \newcount\lst@pos % \global
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{InitVarsEOL}{\global\lst@pos\z@ \global\lst@column\z@}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@lostspace}
% The output macros have to keep track of the difference between the real and desired (current) line width; the latter one given by 'current column times |\lst@width|'.
% More precisely, |\lst@lostspace| equals 'current column times |\lst@width|' minus 'width of so far printed line'.
% Whenever this dimension is positive we can insert space to fix the column alignment.
% \begin{macrocode}
\newdimen\lst@lostspace % \global
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{InitVarsEOL}{\global\lst@lostspace\z@}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@UseLostSpace}
% This is a service macro for the fixed and flexible column output.
% We insert space and reset it (if and) only if |\lst@lostspace| is positive.
% \begin{macrocode}
\def\lst@UseLostSpace{%
\ifdim\lst@lostspace>\z@ %
\kern\lst@lostspace \global\lst@lostspace\z@ %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@InsertLostSpace}
% \begin{macro}{\lst@InsertHalfLostSpace}
% Ditto, but insert always (even if negative).
% \begin{macrocode}
\def\lst@InsertLostSpace{\kern\lst@lostspace \global\lst@lostspace\z@}
\def\lst@InsertHalfLostSpace{%
\global\lst@lostspace.5\lst@lostspace \kern\lst@lostspace}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{aspect}{outputpos}
% Note that there are two |\relax|es \ldots
% \begin{macrocode}
\lst@Aspect{outputpos}{\lstoutputpos@#1\relax\relax}
% \end{macrocode}
% or an empty argument would be bad here.
% We simply test for |l|, |c| and |r|.
% If none of them is given, we issue a warning and assume |r| --- it's default since it looks most bad to me.
% The fixed column format makes use of |\lst@lefthss| and |\lst@righthss|, whereas the flexible needs only |\lst@leftinsert|.
% \begin{macrocode}
\def\lstoutputpos@#1#2\relax{%
\ifx #1l%
\let\lst@lefthss\relax \let\lst@righthss\hss %
\let\lst@leftinsert\relax %
\else\ifx #1c%
\let\lst@lefthss\hss \let\lst@righthss\hss %
\let\lst@leftinsert\lst@InsertHalfLostSpace %
\else %
\let\lst@lefthss\hss \let\lst@righthss\relax %
\let\lst@leftinsert\lst@InsertLostSpace %
\ifx #1r\else \PackageWarning{Listings}%
{Unknown positioning for output boxes}%
\fi %
\fi\fi}
% \end{macrocode}
% \begin{macrocode}
\lstset{outputpos=c}% init
% \end{macrocode}
% \end{aspect}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Dropping empty lines}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@NewLineMacro}
% This macro is assigned to |\lst@NewLine|, which is executed whenever the (next) line is not empty.
% Once called, it deactivates itself.
% \begin{macrocode}
\def\lst@NewLineMacro{%
\global\let\lst@NewLine\relax \par\noindent\hbox{}}
\lst@AddToHook{InitVars}{\global\let\lst@NewLine\lst@NewLineMacro}
% \end{macrocode}
% What we have said about |\lst@NewLine| is not the whole truth.
% Most times we'll assign |\lst@NewLineMacro|, but sometimes we append |\par\noindent\hbox{}| to prepare a new line, namely in the case that the last line has been empty.
% Then |\lst@NewLine| deactivates itself and begins two, three or more (empty) lines.
% This drops empty lines at the end of a listing.
% \begin{macrocode}
\lst@AddToHook{EOL}
{\ifx\lst@NewLine\relax %
\global\let\lst@NewLine\lst@NewLineMacro %
\else %
\lst@AddTo\lst@NewLine{\par\noindent\hbox{}}%
\fi}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Fixed columns}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@OutputOther}
% This macro outputs a character string with nonletters.
% If there is anything to output, we possibly start a new line.
% \begin{macrocode}
\def\lst@OutputOther{%
\ifnum\lst@length=\z@\else %
\lst@NewLine \lst@UseLostSpace %
% \end{macrocode}
% The box must take |\lst@length| characters, each |\lst@width| wide.
% \begin{macrocode}
\hbox to \lst@length\lst@width{%
\lst@lefthss %
\lsthk@OutputOther %
\expandafter\lst@FillOutputBox\the\lst@token\relax %
\lst@righthss}%
% \end{macrocode}
% Finally we hold up the current column, empty the token and close the starting 'if token not empty'.
% \begin{macrocode}
\global\advance\lst@pos -\lst@length %
\lst@token{}\lst@length\z@ %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@Output}
% We reset |\lst@lastother| and use |\lst@thestyle|.
% \begin{macrocode}
\def\lst@Output{%
\let\lst@lastother\relax %
\ifnum\lst@length=\z@\else %
\lst@NewLine \lst@UseLostSpace %
\hbox to \lst@length\lst@width{%
\lst@lefthss %
\lsthk@Output \lst@thestyle{%
\expandafter\lst@FillOutputBox\the\lst@token\relax}%
\lst@righthss}%
\global\advance\lst@pos -\lst@length %
\lst@token{}\lst@length\z@ %
\fi}
% \end{macrocode}
% Note that |\lst@lastother| becomes equivalent to |\relax| and not equivalent to |\@empty| as in all other places (e.g.\ InitVarsEOL).
% I don't know whether this will be important in future or not.
% \end{macro}
%
% \begin{macro}{\lst@FillOutputBox}
% Filling up a box is easy.
% If we come to the end (the |\relax| from above), we do nothing.
% Otherwise we output the argument, insert dynamic space and call the macro again.
% \begin{macrocode}
\def\lst@FillOutputBox#1{%
\ifx\relax#1\else #1\hss\expandafter\lst@FillOutputBox \fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@GotoTabStop}
% For fixed column format we only need to advance |\lst@lostspace| (which is inserted by the output macros above) and update the column.
% \begin{macrocode}
\def\lst@GotoTabStop{%
\global\advance\lst@lostspace \lst@length\lst@width %
\global\advance\lst@column\lst@length \lst@length\z@}%
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Flexible columns}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@OutputOtherFlexible}
% If there is something to output, we first insert the space lost by the flexible column format.
% Then we typeset the box and update the lost space.
% Note that we don't use any |\hss| here.
% \begin{macrocode}
\def\lst@OutputOtherFlexible{%
\ifnum\lst@length=\z@\else %
\lst@NewLine \lst@UseLostSpace %
\setbox\@tempboxa\hbox{\lsthk@OutputOther\the\lst@token}%
\lst@CalcLostSpaceAndOutput %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@OutputFlexible}
% Nothing is new here.
% \begin{macrocode}
\def\lst@OutputFlexible{%
\let\lst@lastother\relax %
\ifnum\lst@length=\z@\else %
\lst@NewLine \lst@UseLostSpace %
\setbox\@tempboxa\hbox{%
\lsthk@Output \lst@thestyle{\the\lst@token}}%
\lst@CalcLostSpaceAndOutput %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@GotoTabStopFlexible}
% Here we look whether or not the line already contains printing characters.
% \begin{macrocode}
\def\lst@GotoTabStopFlexible{%
\ifx\lst@NewLine\relax %
% \end{macrocode}
% If some characters are already printed, we output a box, which has the width of a blank space.
% Possibly more space is inserted, but that's upto the current value of |\lst@lostspace|.
% \begin{macrocode}
\setbox\@tempboxa\hbox{\lst@outputblank}\@tempdima\wd\@tempboxa%
\setbox\@tempboxa\hbox{}\wd\@tempboxa\@tempdima %
\lst@CalcLostSpaceAndOutput %
\global\lst@pos\z@ %
\else %
% \end{macrocode}
% Otherwise (no printed characters) we do the same as for fixed columns.
% \begin{macrocode}
\global\advance\lst@lostspace \lst@length\lst@width %
\global\advance\lst@column\lst@length \lst@length\z@ %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@CalcLostSpaceAndOutput}
% The update of |\lst@lostspace| is simple, refer its definition above (difference between \ldots).
% \begin{macrocode}
\def\lst@CalcLostSpaceAndOutput{%
\global\advance\lst@lostspace \lst@length\lst@width %
\global\advance\lst@lostspace-\wd\@tempboxa %
% \end{macrocode}
% Moreover we keep track of |\lst@pos| and reset some variables.
% \begin{macrocode}
\global\advance\lst@pos -\lst@length %
\lst@token{}\lst@length\z@ %
% \end{macrocode}
% Before |\@tempboxa| is output, we insert appropiate space if there is enough lost space.
% \begin{macrocode}
\ifdim\lst@lostspace>\z@ \lst@leftinsert \fi %
\box\@tempboxa}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Dropping the whole output}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@BeginDropOutput}
% It's sometimes useful to process a part of a listing as usual, but to drop the output.
% This macro does the main work and gets one argument, namely the internal mode it enters.
% We save |\lst@NewLine|, restore it |\aftergroup| and redefine the output macros.
% \begin{macrocode}
\def\lst@BeginDropOutput#1{%
\let\lst@BDOsave\lst@NewLine %
\lst@EnterMode{#1}%
{\lst@modetrue %
\let\lst@Output\lst@EmptyOutput %
\let\lst@OutputOther\lst@EmptyOutputOther %
\let\lst@GotoTabStop\lst@EmptyGotoTabStop %
\aftergroup\lst@BDORestore}}
% \end{macrocode}
% Restoring |\lst@NewLine| is quite easy:
% \begin{macrocode}
\def\lst@BDORestore{\global\let\lst@NewLine\lst@BDOsave}
% \end{macrocode}
% Note that there is no |\lst@EndDropOutput| since this macro would be equivalent to |\lst@LeaveMode|.
% \end{macro}
%
% \begin{macro}{\lst@EmptyOutputOther}
% \begin{macro}{\lst@EmptyOutput}
% \begin{macro}{\lst@EmptyGotoTabStop}
% Here we only keep track of registers (possibly) needed by other processing macros.
% \begin{macrocode}
\def\lst@EmptyOutputOther{%
\global\advance\lst@pos -\lst@length %
\lst@token{}\lst@length\z@}
% \end{macrocode}
% \begin{macrocode}
\def\lst@EmptyOutput{\let\lst@lastother\relax \lst@EmptyOutputOther}
% \end{macrocode}
% \begin{macrocode}
\def\lst@EmptyGotoTabStop{%
\global\advance\lst@column\lst@length \lst@length\z@}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Writing to an external file}
%
% The macros are defined (if and) only if the |doc| option is used.
% \begingroup
% \begin{macrocode}
%<*kernel>
\@ifundefined{lst@doc}{}{%
% \end{macrocode}
% \endgroup
%
% \begin{macro}{\lstdoc@out}
% The file we will write to.
% \begin{macrocode}
\newwrite\lstdoc@out
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@BeginWriteFile}
% redefines some macros to meet our purpose.
% The file with name |#1| is opened at the end of the macro.
% \begin{macrocode}
\def\lst@BeginWriteFile#1{%
\begingroup %
\lsthk@SetLanguage %
\let\lstCC@ifec\iffalse %
\let\lst@Output\lstdoc@Output %
\let\lst@OutputOther\lstdoc@Output %
\let\lst@GotoTabStop\lstdoc@GotoTabStop %
\let\lstCC@ProcessSpace\lstdoc@ProcessSpace %
\let\lst@MProcessListing\lstdoc@MProcessListing %
\let\smallbreak\relax %
\let\lst@prelisting\relax \let\lst@postlisting\relax %
\let\lst@@prelisting\relax \let\lst@@postlisting\relax %
\let\lstCC@Use\lstdoc@Use %
\let\lst@DeInit\lstdoc@DeInit %
\immediate\openout\lstdoc@out=#1\relax}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@EndWriteFile}
% closes the file and restores original macro meanings.
% \begin{macrocode}
\def\lst@EndWriteFile{\immediate\closeout\lstdoc@out \endgroup}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstdoc@Output}
% keeps only track of horizontal position.
% \begin{macrocode}
\def\lstdoc@Output{\global\advance\lst@pos -\lst@length \lst@length\z@}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstdoc@ProcessSpace}
% \begin{macro}{\lstdoc@GotoTabStop}
% We append the appropiate number of spaces.
% Note that |\lstCC@Append| increases |\lst@length| by 1, thus we need -2.
% \begin{macrocode}
\def\lstdoc@ProcessSpace{\lstCC@Append{ }}
\def\lstdoc@GotoTabStop{%
\@whilenum \lst@length>\z@ \do %
{\lstCC@Append{ }\advance\lst@length-2\relax}}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lstdoc@MProcessListing}
% writes one line to external file.
% \begin{macrocode}
\def\lstdoc@MProcessListing{%
\immediate\write\lstdoc@out{\the\lst@token}%
\lst@token{}\lst@length\z@ %
\lst@BOLGobble}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstdoc@DeInit}
% We write the rest to file and end processing.
% \begin{macrocode}
\def\lstdoc@DeInit{%
\ifnum\lst@length=\z@\else %
\immediate\write\lstdoc@out{\the\lst@token}%
\fi %
\egroup \smallbreak\lst@postlisting \endgroup}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstdoc@Use}
% Any processed character appends the character itself to |\lst@token| (but with catcode 12 or 10).
% The original |\lstCC@Use| is defined in section \ref{iCharacterTables}.
% \begin{macrocode}
\def\lstdoc@Use#1#2#3{%
\ifnum#2=\z@ %
\expandafter\@gobbletwo %
\else %
\catcode#2=\active \lccode`\~=#2\lccode`\/=#2%
\lowercase{\def~{\lstCC@Append{/}}}%
\fi %
\lstdoc@Use#1}
% \end{macrocode}
% \end{macro}
%
% \begingroup
% \begin{macrocode}
}% of \@ifundefined{lst@doc}{}{%
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Keyword comments}
%
% \begingroup
% \begin{macrocode}
%<*keywordcomments>
% \end{macrocode}
% \endgroup
% \begin{aspect}{keywordcomment}
% \begin{aspect}{doublekeywordcommentsemicolon}
% The same stuff as for the other comment commands.
% \begin{macrocode}
\lst@Aspect{keywordcomment}
{\lst@MakeKeywordArg{#1}\let\lst@KCkeywords\lst@arg %
\let\lst@DefKC\lstCC@KeywordComment}
% \end{macrocode}
% \begin{macrocode}
\lst@Aspect{doublekeywordcommentsemicolon}{\lstDKCS@#1}
\gdef\lstDKCS@#1#2#3%
{\lst@MakeKeywordArg{#1}\let\lst@KCAkeywordsB\lst@arg %
\lst@MakeKeywordArg{#2}\let\lst@KCAkeywordsE\lst@arg %
\lst@MakeKeywordArg{#3}\let\lst@KCBkeywordsB\lst@arg %
\let\lst@DefKC\lstCC@DoubleKeywordCommentS}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{SelectCharTable}{\lst@DefKC}
\lst@AddToHook{BeforeSelectCharTable}
{\lst@ifsensitive\else %
\lst@MakeMacroUppercase\lst@KCkeywords %
\lst@MakeMacroUppercase\lst@KCAkeywordsB %
\lst@MakeMacroUppercase\lst@KCAkeywordsE %
\lst@MakeMacroUppercase\lst@KCBkeywordsB %
\fi}
\lst@AddToHook{SetLanguage}{%
\let\lst@DefKC\relax \let\lst@KCkeywords\@undefined %
\let\lst@KCAkeywordsB\@undefined \let\lst@KCAkeywordsE\@undefined %
\let\lst@KCBkeywordsB\@undefined}
% \end{macrocode}
% \end{aspect}\end{aspect}
%
% \begin{macro}{\lstCC@KeywordComment}
% For this type of keyword comments we save the old output macro and install a new one.
% Note that |\lstCC@KeywordComment| is executed after selecting the character table via |\lst@DefKC|.
% \begin{macrocode}
\gdef\lstCC@KeywordComment{%
\let\lst@Output@\lst@Output \let\lst@Output\lst@KCOutput}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@KCOutput}
% And now we look how the output works here.
% It starts as all the time.
% But if the current character sequence in |\lst@token| is one of the given keywords, we call a macro which starts and ends keyword comments.
% |\lst@next| is redefined there.
% After doing all this, we output the token as usual and go on.
% \begin{macrocode}
\gdef\lst@KCOutput{%
\ifnum\lst@length=\z@\else %
\let\lst@next\relax %
\expandafter\lst@IfOneOf \the\lst@token\relax \lst@KCkeywords %
{\lst@KCOutput@\lst@BeginKC}{}%
\lst@Output@ \lst@next %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@KCOutput@}
% Now we are in the situation that the current token is attached to a keyword comment.
% By default |\lst@next| becomes equivalent to the first argument, which is either |\lst@BeginKC| or |\lst@BeginDKCA| or |\lst@BeginDKCB|.
% Moreover we save the current token.
% \begin{macrocode}
\gdef\lst@KCOutput@#1{\let\lst@next#1%
\expandafter\def\expandafter\lst@save\expandafter{\the\lst@token}%
% \end{macrocode}
% If we are not in 'keyword comment mode', nothing else is done here.
% But if we are, we must end the comment.
% The problem: Closing the comment group also ruins the current character string in |\lst@token|.
% The solution: We define a global macro to restore the token and |\lst@length|.
% |\@gtempa| becomes
% \begin{itemize}\item[]
% |\lst@token{|\meta{current character string}|}\lst@length|\meta{current length}|\relax|
% \end{itemize}
% \begin{macrocode}
\lst@ifmode \ifnum\lst@mode=\lst@KCmode %
\xdef\@gtempa{%
\noexpand\lst@token{\the\lst@token}%
\noexpand\lst@length\the\lst@length\relax}%
% \end{macrocode}
% This macro is executed after closing the comment group.
% We redefine |\lst@next| just to |\relax|.
% \begin{macrocode}
\aftergroup\@gtempa \lst@LeaveMode \let\lst@next\relax %
\fi \fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@BeginKC}
% We call |\lstCC@BeginComment| and define |\lst@KCkeywords| to be the current token (possibly made upper case) since we want a matching keyword.
% Note: It's a local definition, i.e.\ after ending the comment all comment starting keywords are restored.
% \begin{macrocode}
\gdef\lst@BeginKC{%
\lstCC@BeginComment\lst@KCmode \let\lst@KCkeywords\lst@save %
\lst@ifsensitive\else \lst@MakeMacroUppercase\lst@KCkeywords \fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@DoubleKeywordCommentS}
% Let's look at the next macro collection.
% The first macro is the same as the first from above --- except that we must install a different semicolon, which is done at the very beginning.
% \begin{macrocode}
\gdef\lstCC@DoubleKeywordCommentS{%
\lstCC@EndKeywordComment{"003B}%
\let\lst@Output@\lst@Output \let\lst@Output\lst@DKCOutput}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@DKCOutput}
% The second macro is also the same as above, but if we haven't found a keyword from the |KCA| list, we try the |KCB| list.
% \begin{macrocode}
\gdef\lst@DKCOutput{%
\ifnum\lst@length=\z@\else %
\let\lst@next\relax %
\expandafter\lst@IfOneOf \the\lst@token\relax\lst@KCAkeywordsB %
{\lst@KCOutput@\lst@BeginDKCA}{%
\expandafter\lst@IfOneOf \the\lst@token\relax\lst@KCBkeywordsB %
{\lst@KCOutput@\lst@BeginDKCB}{}}%
\lst@Output@ \lst@next %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@BeginDKCA}
% \begin{macro}{\lst@BeginDKCB}
% To begin a keyword comment, we assign appropiate lists of keywords, which might end the comment.
% \begin{macrocode}
\gdef\lst@BeginDKCA{\lstCC@BeginComment\lst@KCmode %
\let\lst@KCAkeywordsB\lst@KCAkeywordsE \let\lst@KCBkeywordsB\@empty}
% \end{macrocode}
% \begin{macrocode}
\gdef\lst@BeginDKCB{\lstCC@BeginComment\lst@KCmode %
\let\lst@KCAkeywordsB\@empty \let\lst@KCBkeywordsB\@empty}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lstCC@EndKeywordComment}
% Above we've installed a 'end keyword comment' semicolon.
% Before reading further you should be familiar with section \ref{iCharacterTables}.
% Roughly speaking we define commands there, which annouces the source code character $0041_{\mathrm{hex}}$='A' to be the upper case letter 'A'.
% The macro here announces a character to end keyword comments.
% \begin{macrocode}
\gdef\lstCC@EndKeywordComment#1{%
\lccode`\~=#1\lowercase{\lstCC@EndKeywordComment@~}{#1}}
% \end{macrocode}
% Looking at the submacro, |#1| is an active character with ASCII code |#2|.
% We must save a previous meaning of |#1| --- or we couldn't output the character since we've forgotten it.
% Afterwards we can redefine it: If we are in comment mode and furthermore in keyword comment mode, the 'end keyword comment' character ends the comment, as desired.
% Note that we output the old meaning of the character first.
% \begin{macrocode}
\gdef\lstCC@EndKeywordComment@#1#2{%
\expandafter\let\csname lstCC@EKC#2\endcsname#1%
\def#1{%
\ifnum\lst@mode=\lst@KCmode %
\let\lstCC@next\lstCC@EndComment %
\else %
\let\lstCC@next\relax %
\fi %
\csname lstCC@EKC#2\endcsname \lstCC@next}}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</keywordcomments>
% \end{macrocode}
% \endgroup
%
%
% \section{Character classes}\label{iCharacterClasses}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \TeX{} knows sixteen category codes.
% We define our own character classes here.
% Each input character becomes active in the sense of \TeX{} and characters of different classes expand to different meanings.
% We use the following ones:
% \begin{itemize}
% \item letters --- characters identifiers are of;
% \item digits --- characters for identifiers or numerical constants;
% \item spaces --- characters treated as blank spaces;
% \item tabulators --- characters treated as tabulators;
% \item stringizers --- characters beginning and ending strings;
% \item comment indicators --- characters or character sequences beginning and ending comments;
% \item special classes support particular programming languages;
% \item others --- all other characters.
% \end{itemize}
% How these classes work together?
% The digit '3' appends the digit to the current character string, e.g.\ |ear| becomes |ear3|.
% The next nonletter causes the output of the gathered characters.
% Then we collect all coming nonletters until reaching a letter again.
% This causes the output of the nonletters, and so on.
%
% But there are more details.
% Stringizers and comment indicators change the processing mode until the string or the comment is over.
% For example, no keyword tests are done within a string or comment.
% A tabulator immediately outputs the gathered characters, without looking whether they are letters or not.
% Afterwards it is possible to determine the tabulator skip.
% And there is one thing concerning spaces:
% Many spaces following each other disturb the column alignment since they are not wide enough.
% Hence, when column alignment is on, we output the space(s) preceding a space.
%
% The above classes can be divided into three types:
% \begin{itemize}
% \item The 'letter', 'digit' and 'other' class all put characters into the 'output queue' (using |\lstCC@Append| or |\lstCC@AppendOther|, see below).
% \item Stringizer, comment indicators and special classes don't affect the output queue directly.
% For example, before a character becomes a stringizer, the 'letter', 'digit' or 'other' meaning is saved.
% Now the stringizer accesses the output queue via this saved meaning.
% \item Spaces and tabulators don't put any character into the output queue, but may affect the queue to do their job, as mentioned above.
% Instances of these classes are not overwritten (in contrast to letters, digits and others).
% \end{itemize}
% Some easy implementation before looking closer \ldots
%
% \begin{macro}{\lstCC@Append}
% This macro appends the argument to the current character string and increases the counter |\lst@length|.
% \begin{macrocode}
\def\lstCC@Append#1{\advance\lst@length\@ne %
\expandafter\lst@token\expandafter{\the\lst@token#1}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@AppendOther}
% Nearly the same, but we save the argument (a single character or a single macro) in |\lst@lastother|.
% \begin{macrocode}
\def\lstCC@AppendOther#1{\advance\lst@length\@ne \let\lst@lastother#1%
\expandafter\lst@token\expandafter{\the\lst@token#1}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@ifletter}
% This \texttt{if} indicates whether the last character has been a letter or not.
% \begin{macrocode}
\def\lstCC@lettertrue{\let\lstCC@ifletter\iftrue}
\def\lstCC@letterfalse{\let\lstCC@ifletter\iffalse}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{InitVars}{\lstCC@letterfalse}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@PrintToken}
% This macro outputs the current character string in letter or nonletter mode.
% \begin{macrocode}
\def\lst@PrintToken{%
\lstCC@ifletter %
\lst@Output\lstCC@letterfalse %
\else %
\lst@OutputOther \let\lst@lastother\@empty %
\fi}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Character tables}\label{iCharacterTables}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% Before looking at interesting character classes we do some rather tedious coding.
% Consider a source file of a programming language now.
% For example, the character $41_{\mathrm{hex}}=65_{\mathrm{dec}}$ usually belongs to the letter class and represents the letter 'A'.
% The listings package says |\lstCC@Use\lstCC@ProcessLetter|\ldots|{"41}{A}|\ldots\ to make this clear.
% Roughly speaking it expands to |\def A{\lstCC@ProcessLetter A}|, but the first 'A' is active and the second not.
%
% \begin{macro}{\lstCC@Def}
% \begin{macro}{\lstCC@Let}
% For speed we won't used these helpers too often.
% The letter 'A' definition from above could be achieved via |\lstCC@Def{"41}{\lstCC@ProcessLetter A}|.
% \begin{macrocode}
\def\lstCC@Def#1{\catcode#1=\active\lccode`\~=#1\lowercase{\def~}}
\def\lstCC@Let#1{\catcode#1=\active\lccode`\~=#1\lowercase{\let~}}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@SelectCharTable}
% Each input character becomes active and gets the correct meaning here.
% We change locally the catcode of the double quote for compatibility with \texttt{german.sty}.
% Note that some macros take one argument and others a series of arguments which is terminated by |{"00}{}| (or an equivalent expression).
% \begin{macrocode}
\begingroup \catcode`\"=12
\gdef\lst@SelectCharTable{%
\lstCC@Tabulator{"09}%
\lstCC@Space{"20}%
\lstCC@Use \lstCC@ProcessOther %
{"21}!{"22}"{"23}\#{"25}\%{"26}\&{"27}'{"28}({"29})%
{"2A}\lst@asterisk{"2B}+{"2C},{"2D}\lst@minus{"2E}.%
{"2F}/{"3A}:{"3B};{"3C}\lst@less{"3D}={"3E}\lst@greater{"3F}?%
{"5B}[{"5C}\lst@backslash{"5D}]{"5E}\textasciicircum{"60}{`}%
{"7B}\lst@lbrace{"7C}\lst@bar{"7D}\lst@rbrace %
{"7E}\textasciitilde{"7F}-%
\z@\@empty %
\lstCC@Use \lstCC@ProcessDigit %
{"30}0{"31}1{"32}2{"33}3{"34}4{"35}5{"36}6{"37}7{"38}8{"39}9%
\z@\@empty %
\lstCC@Use \lstCC@ProcessLetter %
{"24}\lst@dollar{"40}@%
{"41}A{"42}B{"43}C{"44}D{"45}E{"46}F{"47}G{"48}H{"49}I{"4A}J%
{"4B}K{"4C}L{"4D}M{"4E}N{"4F}O{"50}P{"51}Q{"52}R{"53}S{"54}T%
{"55}U{"56}V{"57}W{"58}X{"59}Y{"5A}Z{"5F}\lst@underscore %
{"61}a{"62}b{"63}c{"64}d{"65}e{"66}f{"67}g{"68}h{"69}i{"6A}j%
{"6B}k{"6C}l{"6D}m{"6E}n{"6F}o{"70}p{"71}q{"72}r{"73}s{"74}t%
{"75}u{"76}v{"77}w{"78}x{"79}y{"7A}z%
\z@\@empty %
% \end{macrocode}
% Define extended characters 128--255.
% \begin{macrocode}
\lstCC@ifec \lstCC@DefEC \fi %
% \end{macrocode}
% Finally we call some (hook) macros and initialize the backslash if necessary.
% \begin{macrocode}
\lsthk@SelectCharTable %
\csname lstSCT@\lst@language\endcsname %
\csname lstSCT@\lst@language @\lst@dialect\endcsname %
\ifx\lstCC@Backslash\relax\else %
\lccode`\~="5C\lowercase{\let\lsts@backslash~}%
\lstCC@Let{"5C}\lstCC@Backslash %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@DefEC}
% Currently each character in the range 128--255 is treated as a letter.
% \begin{macrocode}
\catcode`\^^@=12
\gdef\lstCC@DefEC{%
\lstCC@ECUse \lstCC@ProcessLetter %
^^80^^81^^82^^83^^84^^85^^86^^87^^88^^89^^8a^^8b^^8c^^8d^^8e^^8f%
^^90^^91^^92^^93^^94^^95^^96^^97^^98^^99^^9a^^9b^^9c^^9d^^9e^^9f%
^^a0^^a1^^a2^^a3^^a4^^a5^^a6^^a7^^a8^^a9^^aa^^ab^^ac^^ad^^ae^^af%
^^b0^^b1^^b2^^b3^^b4^^b5^^b6^^b7^^b8^^b9^^ba^^bb^^bc^^bd^^be^^bf%
^^c0^^c1^^c2^^c3^^c4^^c5^^c6^^c7^^c8^^c9^^ca^^cb^^cc^^cd^^ce^^cf%
^^d0^^d1^^d2^^d3^^d4^^d5^^d6^^d7^^d8^^d9^^da^^db^^dc^^dd^^de^^df%
^^e0^^e1^^e2^^e3^^e4^^e5^^e6^^e7^^e8^^e9^^ea^^eb^^ec^^ed^^ee^^ef%
^^f0^^f1^^f2^^f3^^f4^^f5^^f6^^f7^^f8^^f9^^fa^^fb^^fc^^fd^^fe^^ff%
^^00}
\endgroup
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{extendedchars}
% The user aspect.
% \begin{macrocode}
\lst@Aspect{extendedchars}[t]{\lstKV@SetIfKey\lstCC@ifec{#1}}
\lstset{extendedchars=false}% init
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lstCC@Use}
% Now we define the |\lstCC@|\ldots|Use| macros used above.
% We either define the character with code |#2| to be |#1#3| (where |#1| is |\lstCC@ProcessLetter| for example) or we gobble the two token after |\fi| to terminate the loop.
% \begin{macrocode}
\def\lstCC@Use#1#2#3{%
\ifnum#2=\z@ %
\expandafter\@gobbletwo %
\else %
\catcode#2=\active \lccode`\~=#2\lowercase{\def~}{#1#3}%
\fi %
\lstCC@Use#1}
% \end{macrocode}
% Limitation: Each second argument to |\lstCC@Use| (beginning with the third one) must be exactly one character or one control sequence.
% The reason is not the definition here.
% |\lst@AppendOther| says |\let\lst@lastother#1| and that works with the mentioned limitation only.
% I'll get over this since |\let| is faster than |\def|, and that's the motivation.
% \emph{Caution}: Don't change that |\let| to a definition with |\def|.
% All |\ifx\lst@lastother|\ldots{} in all character classes wouldn't work any more!
% And rewriting all this would slow down the package.
% Beware of that.
% \end{macro}
%
% \begin{macro}{\lstCC@ECUse}
% Here we have two arguments only, namely |\lstCC@ProcessLetter|,\ldots\ and the character (and no character code).
% Reaching end of list (|^^00|) we terminate the loop.
% Otherwise we do the same as in |\lstCC@Use| if the character is not active.
% But if the character is active, we save the meaning before redefinition.
% \begin{macrocode}
\def\lstCC@ECUse#1#2{%
\ifnum`#2=\z@ %
\expandafter\@gobbletwo %
\else %
\ifnum\catcode`#2=\active %
\lccode`\~=`#2\lccode`\/=`#2\lowercase{\lstCC@ECUse@#1~/}%
\else %
\catcode`#2=\active \lccode`\~=`#2\lowercase{\def~}{#1#2}%
\fi %
\fi %
\lstCC@ECUse#1}
% \end{macrocode}
% As mentioned, we save the meaning before redefinition.
% \begin{macrocode}
\def\lstCC@ECUse@#1#2#3{%
\expandafter\let\csname lsts@EC#3\endcsname #2%
\edef#2{\noexpand#1\expandafter\noexpand\csname lsts@EC#3\endcsname}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@Tabulator}
% \begin{macro}{\lstCC@Space}
% The similar space and tabulator macros have one argument only (no loop and no macro or character).
% \begin{macrocode}
\def\lstCC@Tabulator#1{\lstCC@Let{#1}\lstCC@ProcessTabulator}
\def\lstCC@Space#1{\lstCC@Let{#1}\lstCC@ProcessSpace}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lstCC@ChangeBasicClass}
% Finally we define a macro (collection) with the ability of moving a basic \emph{instance} of class to another class, e.g. making the digit '0' be a letter.
% The word 'basic' means any instance defined with |\lstCC@Use| or |\lstCC@ECUse|.
% The first argument of |\lstCC@ChangeBasicClass| gives the new class and the second argument is a macro containing a character sequence.
% These characters are changed.
% First we make all these characters active and call a submacro.
% \begin{macrocode}
\def\lstCC@ChangeBasicClass#1#2{%
\ifx\@empty#2\else %
\expandafter\lst@MakeActive\expandafter{#2}%
\expandafter\lstCC@CBC@\expandafter#1\lst@arg\@empty %
\fi}
% \end{macrocode}
% The submacro terminates (gobble two token after |\fi|) if it reaches |\@empty|.
% Otherwise another submacro redfines the character.
% Note that we expand the old meaning before calling the second submacro and that the second |\lstCC@CBC@@| is used as 'meaning' delimiter.
% \begin{macrocode}
\def\lstCC@CBC@#1#2{%
\ifx\@empty#2%
\expandafter\@gobbletwo %
\else %
\expandafter\lstCC@CBC@@#2\lstCC@CBC@@#1#2%
\fi %
\lstCC@CBC@#1}
% \end{macrocode}
% \begin{macrocode}
\def\lstCC@CBC@@#1#2\lstCC@CBC@@#3#4{\def#4{#3#2}}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Letters, digits and others}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lstCC@ProcessLetter}
% To process a letter we look at the last character.
% If it hasn't been a letter, we output the preceding other characters first and switch to letter mode.
% Finally we append the current letter |#1|.
% \begin{macrocode}
\def\lstCC@ProcessLetter#1{%
\lstCC@ifletter\else \lst@OutputOther\lstCC@lettertrue \fi %
\lstCC@Append{#1}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@ProcessOther}
% 'Other' characters are the other way round.
% If the last character has been a letter, the preceding letters are output and we switch to nonletter mode.
% Finally we append the current other character.
% \begin{macrocode}
\def\lstCC@ProcessOther#1{%
\lstCC@ifletter \lst@Output\lstCC@letterfalse \fi %
\lstCC@AppendOther{#1}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@ProcessDigit}
% A digit simply appends the character to the current character string.
% But we must use the right macro.
% This allow digits to be part of an identifier or a numerical constant.
% \begin{macrocode}
\def\lstCC@ProcessDigit#1{%
\lstCC@ifletter \lstCC@Append{#1}\else \lstCC@AppendOther{#1}\fi}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Tabulators and spaces}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% Here we have to take care of two things:
% First dropping empty lines at the end of a listing, and second the flexible column format.
% In both cases we use |\lst@lostspace| for the implementation.
% Whenever this dimension is positive we insert that space before |\lst@token| is output.
%
% We've defined |\lst@EOLUpdate| to drop empty lines at the end of a listing.
% |\lst@NewLine| isn't executed or reset in that case.
% Instead we append control sequences.
% But: Lines containing tabulators and spaces only should also be viewed as empty.
% In order to achieve this tabulators and spaces at the beginning of a line advance |\lst@lostspace| and don't output any characters.
% The space is inserted if there comes a letter for example.
% If there are only tabulators and spaces, the line is 'empty' since we haven't done any output.
%
% We have to do more for flexible columns.
% The whitespaces can fix the column alignment:
% If the real line is wider than it should be (|\lst@lostspace|$<$0pt), a tabulator is at least one space wide; all the other width is used to make |\lst@lostspace| more positive.
% Spaces do the same: If there are two or more spaces, at least one space is printed; the others fix the column alignment.
% If we process a string, all spaces are output, of course.
%
% \begin{macro}{\lstCC@ProcessTabulator}
% A tabulator outputs the preceding characters.
% \begin{macrocode}
\def\lstCC@ProcessTabulator{%
\lst@PrintToken %
% \end{macrocode}
% Then we must calculate how many columns we need to reach the next tabulator stop.
% Each printed character decrements the counter |\lst@pos|.
% Hence we can simply add |\lst@tabsize| until |\lst@pos| is strict positive.
% That's all.
% We assign it to |\lst@length|, reset |\lst@pos| \ldots
% \begin{macrocode}
\global\advance\lst@column -\lst@pos %
\@whilenum \lst@pos<\@ne \do %
{\global\advance\lst@pos\lst@tabsize}%
\lst@length\lst@pos \global\lst@pos\z@ %}
% \end{macrocode}
% and go to the tabulator stop, e.g.\ |\lst@length| columns forward:
% \begin{macrocode}
\lst@GotoTabStop}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@AppendSpecialSpace}
% Sometimes we have special spaces:
% If there are at least two spaces, i.e.\ if the last character have been a space, we output preceding characters and advance |\lst@lostspace| to avoid alignment problems.
% Otherwise we append a space to the current character string.
% We'll need that macro soon.
% \begin{macrocode}
\def\lstCC@AppendSpecialSpace{%
\ifx\lst@lastother\lst@outputblank %
\lst@OutputOther %
\global\advance\lst@lostspace\lst@width %
\global\advance\lst@pos\m@ne %
\else %
\lstCC@AppendOther\lst@outputblank %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@outputblank}
% It's better not to forget this.
% \begin{macrocode}
\def\lst@outputblank{\ }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@ProcessSpace}
% If the last character has been a letter, we output the current character string and append one space.
% \begin{macrocode}
\def\lstCC@ProcessSpace{%
\lstCC@ifletter %
\lst@Output\lstCC@letterfalse %
\lstCC@AppendOther\lst@outputblank %
% \end{macrocode}
% Otherwise we look whether we are in string mode or not.
% In the first case we must append a space; in the second case we must test if the hitherto line is empty.
% \begin{macrocode}
\else \ifnum\lst@mode=\lst@stringmode %
\lstCC@AppendOther\lst@outputblank %
\else \ifx\lst@NewLine\relax %
% \end{macrocode}
% If the line is not empty we either advance |\lst@lostspace| or append a space to the current character string.
% \begin{macrocode}
\lstCC@AppendSpecialSpace %
\else \ifnum\lst@length=\z@ %
% \end{macrocode}
% If the line is empty so far, we advance |\lst@lostspace|.
% Otherwise we append the space.
% \begin{macrocode}
\global\advance\lst@lostspace\lst@width %
\global\advance\lst@pos\m@ne %
\else %
\lstCC@AppendSpecialSpace %
\fi %
\fi \fi \fi}
% \end{macrocode}
% Note that this version works for fixed and flexible column output.
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Stringizer}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lst@legalstringizer}
% Currently there are three different stringizer types: 'd'oubled, 'b'ackslashed and 'm'atlabed.
% The naming of the first two is due to how the stringizer is represented in a string.
% Pascal doubles it, i.e.\ the string |'| is represented by four single quotes |''''|, where the first and last enclose the string and the two middle quotes represent the desired stringizer.
% In C++ we would write |"\""|: A backslash indicates that the next double quote belongs to the string and is not the end of string.
% The matlabed version is described below.
% I introduced it after communication with \lsthelper{Zvezdan V. Petkovic}{zpetkovic@acm.org}{1997/11/26}{'single stringizer' not a stringizer in Ada (and Matlab)}.
% \begin{macrocode}
\def\lst@legalstringizer{d,b,m,bd,db}
% \end{macrocode}
% Furthermore we have the two mixed types |bd| and |db|, which in fact equal |b|.
% \end{macro}
%
% \begin{aspect}{stringizer}
% Here we test whether the user type is supported or not (leading to an error message).
% In the first case we (re-) define |\lst@DefStrings|.
% \begin{macrocode}
\lst@Aspect{stringizer}{\lstKV@OptArg\lststringizer@[d]{#1}}
\def\lststringizer@[#1]#2%
{\lst@IfOneOf#1\relax \lst@legalstringizer %
{\def\lst@DefStrings{\lstCC@Stringizer[#1]#2\@empty}}%
{\PackageError{Listings}{Illegal stringizer type `#1'}%
{Available types are \lst@legalstringizers.}}}
\lst@AddToHook{SetLanguage}{\let\lst@DefStrings\@empty}
\lst@AddToHook{SelectCharTable}{\lst@DefStrings}
% \end{macrocode}
% The just added hook defines the strings after selecting the standard character table.
% This adjusts the character table to the user's demands.
% \end{aspect}
%
% \begin{macro}{\lstCC@Stringizer}
% This macro is similar to |\lstCC@ECUse|, but we build the 'use'd name before defining the characters \ldots
% \begin{macrocode}
\def\lstCC@Stringizer[#1]{%
\expandafter\lstCC@Stringizer@ %
\csname lstCC@ProcessStringizer@#1\endcsname}
\def\lstCC@Stringizer@#1#2{%
\ifx\@empty#2%
\expandafter\@gobbletwo %
% \end{macrocode}
% which is terminated by |\@empty|.
% Otherwise we save the old meaning in |\lsts@s|\meta{the character} (with catcode 12) and redefine it.
% \begin{macrocode}
\else %
\catcode`#2=\active \lccode`\~=`#2\lccode`\/=`#2%
\lowercase{%
\expandafter\let\csname lsts@s/\endcsname~%
\def~{#1/}}%
\fi %
\lstCC@Stringizer@#1}
% \end{macrocode}
% And now we define all 'process stringizer' macros.
% \end{macro}
%
% \begin{macro}{\lstCC@ProcessStringizer@d}
% 'd' means no extra work.
% Reaching the (first) stringizer enters string mode and coming to the next leaves it, and so on.
% Then the character sequence |''''| produces the right output:
% The second quote leaves string mode, but we enter it immediately since the stringizer is doubled.
% And now the implementation.
% First we output any preceding letters.
% \begin{macrocode}
\def\lstCC@ProcessStringizer@d#1{%
\lstCC@ifletter \lst@Output\lstCC@letterfalse \fi %
% \end{macrocode}
% If we already process a string, we execute the saved meaning and look whether the last other (that's the stringizer) is the matching stringizer --- a single quote must not end a string starting with a double quote.
% The macro |\lstCC@EndString| is defined at the end of this section.
% \begin{macrocode}
\ifnum\lst@mode=\lst@stringmode %
\csname lsts@s#1\endcsname %
\ifx\lst@lastother\lstCC@closestring %
\lstCC@EndString %
\fi %
\else %
\lst@OutputOther %
% \end{macrocode}
% If we don't process a string, we test whether or not a string is allowed.
% |\lstCC@BeginString| enters string mode and defines the closing stringizer.
% This 'begin string' macro gets one argument, hence we expand the control sequence name before executing the macro (if necessary).
% \begin{macrocode}
\lst@ifmode\else %
\expandafter\expandafter\expandafter\lstCC@BeginString %
\fi %
\csname lsts@s#1\endcsname %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@ProcessStringizer@b}
% 'b' means an extra if: Only if the last other is not a backslash (5-th line) the stringizer can close the string.
% The rest is the same as above.
% \begin{macrocode}
\def\lstCC@ProcessStringizer@b#1{%
\lstCC@ifletter \lst@Output\lstCC@letterfalse \fi %
\ifnum\lst@mode=\lst@stringmode %
\let\lst@temp\lst@lastother \csname lsts@s#1\endcsname %
\ifx\lst@temp\lst@backslash\else %!def of "005C
\ifx\lst@lastother\lstCC@closestring %
\lstCC@EndString %
\fi \fi %
\else %
\lst@OutputOther %
\lst@ifmode\else %
\expandafter\expandafter\expandafter\lstCC@BeginString %
\fi %
\csname lsts@s#1\endcsname %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@ProcessStringizer@bd}
% \begin{macro}{\lstCC@ProcessStringizer@db}
% are just the same and the same as |\lstCC@ProcessStringizer@b|:
% \begin{macrocode}
\let\lstCC@ProcessStringizer@bd\lstCC@ProcessStringizer@b
\let\lstCC@ProcessStringizer@db\lstCC@ProcessStringizer@bd
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lstCC@ProcessStringizer@m}
% 'm'atlabed is designed for programming languages where stringizers (for character or string literals) are also used for other purposes, like Matlab or Ada.
% Here we enter string mode only if the last character has not been a letter and has not been a right parenthesis.
% Hence, we have to move the |\lstCC@ifletter| and change the main |\else| part.
% By the way: The stringizer is doubled in a string.
% \begin{macrocode}
\def\lstCC@ProcessStringizer@m#1{%
\ifnum\lst@mode=\lst@stringmode %
\lstCC@ifletter \lst@Output\lstCC@letterfalse \fi %
\csname lsts@s#1\endcsname %
\ifx\lst@lastother\lstCC@closestring %
\lstCC@EndString %
\fi %
\else %
% \end{macrocode}
% And now the real 'm' changes:
% \begin{macrocode}
\lstCC@ifletter %
\lst@Output\lstCC@letterfalse %
\else %
\lst@OutputOther %
\let\lstCC@next\relax %
\ifx\lst@lastother)\else \lst@ifmode\else %
\let\lstCC@next\lstCC@BeginString %
\fi \fi %
\expandafter\expandafter\expandafter\lstCC@next %
\fi %
\csname lsts@s#1\endcsname %
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{stringstyle}
% \begin{aspect}{blankstring}
% We insert some easy definitions.
% \begin{macrocode}
\lst@Aspect{stringstyle}{\def\lst@stringstyle{#1}}
% \end{macrocode}
% Thanks to \lsthelper{Knut M\"uller}{knut@physik3.gwdg.de}{1997/04/28}{\blankstringtrue} for reporting problem with |\blankstringtrue|.
% The problem has gone.
% \begin{macrocode}
\lst@Aspect{blankstring}[t]{\lstKV@SetIfKey\lst@ifblankstring{#1}}
% \end{macrocode}
% \begin{macrocode}
\lstset{blankstring=false}% init
\lst@AddToHook{BeforeSelectCharTable}
{\setbox\@tempboxa\hbox{\lst@stringstyle \lst@loadfd}}
% \end{macrocode}
% \end{aspect}\end{aspect}
%
% \begin{macro}{\lst@stringmode}
% It's time for a new mode allocation:
% \begin{macrocode}
\lst@NewMode\lst@stringmode
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@BeginString}
% \begin{macro}{\lstCC@EndString}
% To activate string mode we do te usual things, but here we also assign the correct closing stringizer and |\lst@outputblank|.
% Note that you know that |\lst@NewLine| deactivates itself.
% \begin{macrocode}
\def\lstCC@BeginString#1{%
\lst@NewLine %
\lst@EnterMode{\lst@stringmode}{\lst@modetrue\lst@stringstyle}%
#1%
\let\lstCC@closestring\lst@lastother %
\lst@ifblankstring\else \let\lst@outputblank\textvisiblespace \fi}
% \end{macrocode}
% We terminate that mode selection after printing the collected other characters --- at least the closing stringizer.
% And we reset some registers.
% \begin{macrocode}
\def\lstCC@EndString{%
\lst@OutputOther \lst@LeaveMode \lst@token{}\lst@length\z@}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{aspect}{stringtest}
% We |\let| the test macro |\relax| if necessary.
% \begin{macrocode}
\lst@Aspect{stringtest}[t]{\lstKV@SetIfKey\lst@ifstringtest{#1}}
\lst@AddToHook{SetLanguage}{\let\lst@ifstringtest\iftrue}
\lst@AddToHook{BeforeSelectCharTable}
{\lst@ifstringtest\else \let\lst@TestStringMode\relax \fi}
% \end{macrocode}
% Default definition of the test macro:
% \begin{macrocode}
\def\lst@TestStringMode{%
\ifnum\lst@mode=\lst@stringmode %
\PackageWarning{Listings}{String constant exceeds line}%
\lst@LeaveMode \lst@token{}\lst@length\z@ %
\fi}
\lst@AddToHook{EOL}{\lst@TestStringMode}
% \end{macrocode}
% \end{aspect}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Comments}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{aspect}{commentstyle}
% Again we start with an easy definition.
% \begin{macrocode}
\lst@Aspect{commentstyle}{\def\lst@commentstyle{#1}}
\lst@AddToHook{BeforeSelectCharTable}
{\setbox\@tempboxa\hbox{\lst@commentstyle \lst@loadfd}}
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lstCC@BeginComment}
% \begin{macro}{\lstCC@@BeginComment}
% \begin{macro}{\lstCC@EndComment}
% These macros start and end a comment, respectively.
% The |@@| version also eat (and output) one or two characters.
% In that case the characters belong to the comment indicator.
% |\relax| ensures that the characters are really eaten, i.e.\ the characters can't end the current comment or start a new one.
% Note again that |\lst@NewLine| deactivates itself.
% \begin{macrocode}
\def\lstCC@BeginComment#1{%
\lst@NewLine \lst@PrintToken %
\lst@EnterMode{#1}{\lst@modetrue\lst@commentstyle}}
% \end{macrocode}
% \begin{macrocode}
\def\lstCC@@BeginComment#1#2#3{%
\lst@NewLine \lst@PrintToken %
\lst@EnterMode{#1}{\lst@modetrue\lst@commentstyle}%
\lst@mode\lst@nomode #2\relax#3\relax \lst@mode#1\relax}
% \end{macrocode}
% \begin{macrocode}
\def\lstCC@EndComment{%
\lst@PrintToken \lst@LeaveMode \let\lst@lastother\@empty}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lstCC@TestCArg}
% Comment commands allow a single character like |!| or two characters like |//|.
% The calling syntax of this testing macro is
% \begin{macrosyntax}
% \item |\lstCC@TestCArg|\meta{characters to test}|\@empty\relax|\meta{macro}
% \end{macrosyntax}
% \meta{macro} is called after doing the test and gets three arguments:
% The given two characters as active characters (where the second equals |\@empty| if and only if a single character is given), and the third is a catcode 12 version of the first character.
% \begin{macrocode}
\begingroup \catcode`\^^@=\active
\gdef\lstCC@TestCArg#1#2#3\relax#4{%
\lccode`\~=`#1\lccode`\/=`#1%
\ifx\@empty#2%
\lowercase{\def\lst@temp{~\@empty/}}%
\else \lccode`\^^@=`#2%
\lowercase{\def\lst@temp{~^^@/}}%
\fi %
% \end{macrocode}
% If neither |#2| nor |#3| equals |\@empty|, the user has given more than two characters:
% \begin{macrocode}
\ifx\@empty#2\else \ifx\@empty#3\else \lstCC@TestCArgError \fi\fi %
% \end{macrocode}
% \begin{macrocode}
\expandafter #4\lst@temp}
\endgroup
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@TestCArgError}
% \begin{macrocode}
\def\lstCC@TestCArgError{%
\PackageError{Listings}{At most 2 characters allowed}%
{The package doesn't provide more than two characters here.^^J%
I'll simply use the first two only and proceed.}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@next}
% \begin{macro}{\lstCC@bnext}
% \begin{macro}{\lstCC@enext}
% We initialize some macros used in the sequel.
% \begin{macrocode}
\lst@AddToHook{BeforeSelectCharTable}
{\let\lstCC@next\relax \let\lstCC@bnext\relax\let\lstCC@enext\relax}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lst@DefSC}
% \begin{macro}{\lst@DefNC}
% \begin{macro}{\lst@DefDC}
% \begin{macro}{\lst@DefCL}
% \begin{macro}{\lst@DefFCL}
% These macros are redefined by comment aspects.
% The comments are reset every language selection, and every listing we define the comment characters after selecting the standard character table.
% \begin{macrocode}
\lst@AddToHook{SetLanguage}
{\let\lst@DefSC\relax \let\lst@DefNC\relax \let\lst@DefDC\relax %
\let\lst@DefCL\relax \let\lst@DefFCL\relax}
\lst@AddToHook{SelectCharTable}
{\lst@DefSC \lst@DefNC \lst@DefDC \lst@DefCL \lst@DefFCL}
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}\end{macro}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsubsection{Comment lines}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{aspect}{commentline}
% We define the user aspect:
% \begin{macrocode}
\lst@Aspect{commentline}{\def\lst@DefCL{\lstCC@CommentLine{#1}}}
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lstCC@CommentLine}
% Comment lines become undefined if the one and only argument is empty.
% \begin{macrocode}
\def\lstCC@CommentLine#1{%
\ifx\@empty#1\@empty\else %
\lstCC@TestCArg#1\@empty\relax\lstCC@CommentLine@ %
\fi}
% \end{macrocode}
% The next submacro actually defines the comment characters.
% We save the old meaning --- or we couldn't use the original meaning any more.
% \begin{macrocode}
\def\lstCC@CommentLine@#1#2#3{%
\expandafter\let\csname lsts@CL#3\endcsname#1%
% \end{macrocode}
% The redefinitions:
% If a single character indicates a comment, the next operation is either |\relax| (since no mode change is allowed) or |\lstCC@BeginCommentLine|.
% And we execute the saved character meaning.
% \begin{macrocode}
\ifx\@empty#2%
\def#1{%
\lst@ifmode \let\lstCC@next\relax \else %
\let\lstCC@next\lstCC@BeginCommentLine %
\fi %
\expandafter\lstCC@next \csname lsts@CL#3\endcsname}%
\else %
% \end{macrocode}
% Comment lines indicated by a sequence of two characters are just the same.
% But: We enter comment mode (if and) only if the next character equals |#2|.
% And we use a different macro to enter comment mode.
% \begin{macrocode}
\def#1##1{%
\let\lstCC@next\relax %
\lst@ifmode\else \ifx##1#2%
\let\lstCC@next\lstCC@@BeginCommentLine %
\fi \fi %
\expandafter\lstCC@next \csname lsts@CL#3\endcsname##1}%
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{fixedcommentline}
% \begin{macro}{\lst@FCLmode}
% Another user aspect \ldots
% \begin{macrocode}
\lst@Aspect{fixedcommentline}{\lstKV@OptArg\lstfcommentline@[0]{#1}}
\def\lstfcommentline@[#1]#2%
{\def\lst@DefFCL{\lstCC@FixedCL[#1]#2\@empty}}
% \end{macrocode}
% and a mode allocation.
% \begin{macrocode}
\lst@NewMode\lst@FCLmode
% \end{macrocode}
% \end{macro}\end{aspect}
%
% \begin{macro}{\lstCC@FixedCL}
% Note that we can't use |\lstCC@TestCArg| here since the argument might consist of more than two characters.
% We enter a loop which is terminated by |\@empty|.
% \begin{macrocode}
\def\lstCC@FixedCL[#1]#2{%
\ifx\@empty#2\else %
\lccode`\~=`#2\lccode`\/=`#2%
\lowercase{\lstCC@FixedCL@~/}{#1}%
\def\lstCC@next{\lstCC@FixedCL[#1]}%
\expandafter\lstCC@next %
\fi}
% \end{macrocode}
% But now comes the same as above: We save the old meaning of |#1| and redefine it.
% We enter comment mode (if and) only if the character is in column |#3|+1.
% \begin{macrocode}
\def\lstCC@FixedCL@#1#2#3{%
\expandafter\let\csname lsts@FCL#2\endcsname#1%
\def#1{\let\lstCC@next\relax %
\lst@ifmode\else %
\@tempcnta\lst@column %
\advance\@tempcnta\lst@length %
\advance\@tempcnta-\lst@pos %
\ifnum\@tempcnta=#3%
\let\lstCC@next\lstCC@BeginCommentLine %
\fi %
\fi %
\expandafter\lstCC@next \csname lsts@FCL#2\endcsname}}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsubsection{Single and double comments}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{aspect}{singlecomment}
% \begin{aspect}{doublecomment}
% Define the user commands \ldots
% \begin{macrocode}
\lst@Aspect{singlecomment}{\def\lst@DefSC{\lstCC@SingleComment#1{}}}
\lst@Aspect{doublecomment}{\def\lst@DefDC{\lstCC@DoubleComment#1{}{}{}}}
% \end{macrocode}
% \end{aspect}\end{aspect}
%
% \begin{macro}{\lst@SCmode}
% \begin{macro}{\lst@DCmodeA}
% \begin{macro}{\lst@DCmodeB}
% and allocate new internal modes.
% \begin{macrocode}
\lst@NewMode\lst@SCmode \lst@NewMode\lst@DCmodeA\lst@NewMode\lst@DCmodeB
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lstCC@SingleComment}
% \begin{macro}{\lstCC@DoubleComment}
% All must be done twice here, for the beginning and end of a comment.
% The use of additional arguments like |{SC}\lst@SCmode| make it possible to define single and double comments with the same macros.
% \begin{macrocode}
\def\lstCC@SingleComment#1#2{%
\ifx\@empty#1\@empty\else %
\lstCC@TestCArg#1\@empty\relax\lstCC@CommentB{SC}\lst@SCmode %
\lstCC@TestCArg#2\@empty\relax\lstCC@CommentE{SC}\lst@SCmode %
\fi}
% \end{macrocode}
% Note the order: We define 'begin comment' and afterwards 'end comment'.
% This becomes important if |#1| equals |#2|, for example.
% Each such comment definition saves the old character meaning, which is executed after doing all comment specific.
% If we define 'end comment' first and then 'begin comment', |#1| would start a comment and then execute the old definition, which is 'end comment'.
% Since we are in comment mode now (and since |#1| equals |#2|), 'end comment' leaves comment mode immediately.
% That would be very bad!
% \begin{macrocode}
\def\lstCC@DoubleComment#1#2#3#4{%
\ifx\@empty#1\@empty\else %
\lstCC@TestCArg#1\@empty\relax\lstCC@CommentB{DCA}\lst@DCmodeA %
\lstCC@TestCArg#3\@empty\relax\lstCC@CommentB{DCB}\lst@DCmodeB %
\lstCC@TestCArg#2\@empty\relax\lstCC@CommentE{DCA}\lst@DCmodeA %
\lstCC@TestCArg#4\@empty\relax\lstCC@CommentE{DCB}\lst@DCmodeB %
\fi}
% \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lstCC@CommentB}
% is not different from |\lstCC@CommentLine@| at all:
% The save name |#3| there is replaced by |B#4#3| and instead of |\lst@CLmode| we use |#5|.
% \begin{macrocode}
\def\lstCC@CommentB#1#2#3#4#5{%
\expandafter\let\csname lsts@B#4#3\endcsname#1%
\ifx\@empty#2%
\def#1{%
\lst@ifmode \let\lstCC@bnext\relax \else %
\def\lstCC@bnext{\lstCC@BeginComment#5}%
\fi %
\lstCC@bnext \csname lsts@B#4#3\endcsname}%
\else %
\def#1##1{%
\let\lstCC@bnext\relax %
\lst@ifmode\else \ifx##1#2%
\def\lstCC@bnext{\lstCC@@BeginComment#5}%
\fi \fi %
\expandafter\lstCC@bnext \csname lsts@B#4#3\endcsname##1}%
\fi}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@CommentE}
% Here we insert |\ifnum\lst@mode=#5| (6-th line), where |#5| is |\lst@SCmode| for example.
% This ensures that comment delimiters match each other.
% \begin{macrocode}
\def\lstCC@CommentE#1#2#3#4#5{%
\expandafter\let\csname lsts@E#4#3\endcsname#1%
\ifx\@empty#2%
\def#1{%
\def\lstCC@enext{\csname lsts@E#4#3\endcsname}%
\lst@ifmode \ifnum\lst@mode=#5%
\def\lstCC@enext{\csname lsts@E#4#3\endcsname %
\lstCC@EndComment}%
\fi \fi %
\lstCC@enext}%
\else %
\def#1##1{%
\def\lstCC@enext{\csname lsts@E#4#3\endcsname ##1}%
\lst@ifmode \ifnum\lst@mode=#5\ifx##1#2%
\def\lstCC@enext{\csname lsts@E#4#3\endcsname ##1%
\lstCC@EndComment}%
\fi \fi \fi %
\lstCC@enext}%
\fi}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsubsection{Nested comments}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{aspect}{nestedcomment}
% The user aspect \ldots
% \begin{macrocode}
\lst@Aspect{nestedcomment}{\lstnestedcomment@#1}
\def\lstnestedcomment@#1#2%
{\def\@tempa{#1}\def\@tempb{#2}%
\ifx\@tempa\@tempb \ifx\@tempa\@empty\else %
\PackageError{Listings}{Identical delimitors}%
{These delimitors make no sense with nested comments.}%
\fi \fi %
\def\lst@DefNC{\lstCC@NestedComment{#1}{#2}}}
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lstCC@NestedComment}
% and the internal macro.
% \begin{macrocode}
\def\lstCC@NestedComment#1#2{%
\ifx\@empty#1\@empty\else %
\lstCC@TestCArg#2\@empty\relax\lstCC@NCommentE %
\lstCC@TestCArg#1\@empty\relax\lstCC@NCommentB %
\fi}
% \end{macrocode}
% Note the order: We define 'end comment' and afterwards 'begin comment'.
% \end{macro}
%
% \begin{macro}{\lstCC@NCommentB}
% The redefinition of the character is different now.
% Since we define nested comments, we have to count the comment depth.
% If we already process a nested comment, we increase that depth by making |\lst@mode| more negative.
% \begin{macrocode}
\def\lstCC@NCommentB#1#2#3{%
\let\lsts@BNC #1%
\ifx\@empty#2%
\def#1{%
\let\lstCC@bnext\relax %
\lst@ifmode %
\ifnum\lst@mode<\z@ %
\advance\lst@mode\m@ne %
\fi %
\else %
\def\lstCC@bnext{\lstCC@BeginComment\m@ne}%
\fi %
\lstCC@bnext \lsts@BNC}%
\else %
\def#1##1{%
\let\lstCC@bnext\relax %
\lst@ifmode %
\ifnum\lst@mode<\z@ \ifx##1#2%
\advance\lst@mode\m@ne %
\fi \fi %
\else %
\ifx##1#2%
\def\lstCC@bnext{\lstCC@@BeginComment\m@ne}%
\fi %
\fi %
\lstCC@bnext \lsts@BNC ##1}%
\fi}
% \end{macrocode}
% \begin{TODO}
% The third argument (|\catcode| 12 version of the first) is unused so far --- also in |\lst@NCommentE|.
% If we are in need of 'double' nested comments, we will use this argument for the save name, as we've already done it for normal double comments (and comment lines).
% \end{TODO}
% \end{macro}
%
% \begin{macro}{\lstCC@NCommentE}
% If we are in nested comment mode, we either end the comment or decrease the comment depth by making |\lst@mode| less negative.
% \begin{macrocode}
\def\lstCC@NCommentE#1#2#3{%
\let\lsts@ENC #1%
\ifx\@empty#2%
\def#1{%
\let\lstCC@enext\relax %
\lst@ifmode \ifnum\lst@mode<\z@ %
\ifnum\lst@mode=\m@ne %
\let\lstCC@enext\lstCC@EndComment %
\else %
\advance\lst@mode\@ne %
\fi
\fi \fi %
\lsts@ENC \lstCC@enext}%
\else %
\def#1##1{%
\def\lstCC@enext{\lsts@ENC ##1}%
\ifx##1#2%
\lst@ifmode \ifnum\lst@mode<\z@ %
\ifnum\lst@mode=\m@ne %
\def\lstCC@enext{%
\lsts@ENC ##1\lstCC@EndComment}%
\else %
\advance\lst@mode\@ne %
\fi
\fi \fi %
\fi %
\lstCC@enext}%
\fi}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Escape characters}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% The introduction of this character class is due to a communication with \lsthelper{Rui Oliveira}{rco@di.uminho.pt}{1998/06/05}{escape characters}.
%
% \begin{macro}{\lstCC@Escape}
% gets three arguments all in all.
% The first is the escape character, the second is executed when the escape starts and the third right before ending it.
% We use the same grouping mechanism as for \TeX\ comment lines.
% \begin{macrocode}
\def\lstCC@Escape#1{\lccode`\~=`#1\lowercase{\lstCC@Escape@~}}
\def\lstCC@Escape@#1#2#3{%
\def#1{%
\lst@NewLine\lst@UseLostSpace \lst@PrintToken %
\lst@InterruptModes %
\lst@EnterMode{\lst@TeXmode}{\lst@modetrue}%
% \end{macrocode}
% After doing the grouping we must define the character to end the escape.
% \begin{macrocode}
\catcode`#1=\active %
\def#1{#3\lst@LeaveAllModes \lst@ReenterModes}%
#2}}
% \end{macrocode}
% \begin{macrocode}
\lst@NewMode\lst@TeXmode
% \end{macrocode}
% \end{macro}
%
% \begin{aspect}{escapechar}
% This aspect defines |\lst@DefEsc|, which is executed after selecting the standard character table.
% \begin{macrocode}
\lst@Aspect{escapechar}
{\ifx\@empty#1\@empty %
\let\lst@DefEsc\relax %
\else %
\def\lst@DefEsc{\lstCC@Escape{#1}\@empty\@empty}%
\fi}
% \end{macrocode}
% \begin{macrocode}
\lstset{escapechar={}}% init
\lst@AddToHook{SelectCharTable}{\lst@DefEsc}
% \end{macrocode}
% \end{aspect}
%
% \begin{aspect}{mathescape}
% A switch tested after character table selection.
% We use |\lstCC@Escape| with math shifts as arguments.
% \begin{macrocode}
\lst@Aspect{mathescape}[t]{\lstKV@SetIfKey\lst@ifmathescape{#1}}
\lstset{mathescape=false}% init
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{SelectCharTable}
{\lst@ifmathescape \lstCC@Escape{\$}{$}{$}\fi}
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lst@DontEscapeToLaTeX}
% This macro came in handy.
% \begin{macrocode}
\def\lst@DontEscapeToLaTeX{%
\let\lst@iftexcl\iffalse %
\let\lst@DefEsc\relax %
\let\lst@ifmathescape\iffalse}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \section{More \texttt{lst}-aspects and classes}
%
%
% \subsection{Form feeds}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{aspect}{formfeed}
% We begin with the announcement --- the introduction is due to communication with \lsthelper{Jan Braun}{Jan.Braun@tu-bs.de}{1998/04/27}{\lstformfeed}.
% \begin{macrocode}
\lst@Aspect{formfeed}{\def\lst@formfeed{#1}}
\lstset{formfeed=\bigbreak}% init
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{SelectCharTable}{\lstCC@Let{`\^^L}\lstCC@FormFeed}
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lstCC@FormFeed}
% Here we either execute some macros or append them to |\lst@NewLine|.
% \begin{macrocode}
\def\lstCC@FormFeed{%
\lst@PrintToken %
\ifx\lst@NewLine\relax %
\lst@EOLUpdate \lst@formfeed %
\else %
\lst@lAddTo\lst@NewLine{\lst@EOLUpdate \lst@formfeed}%
\fi}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \subsection{\TeX\ control sequences}
%
% \begingroup
% \begin{macrocode}
%<*tex>
% \end{macrocode}
% \endgroup
% \begin{aspect}{texcs}
% In general, it's the same as |keywords|, but control sequences are case sensitive, have a preceding backslash, \ldots
% \begin{macrocode}
\lst@Aspect{texcs}{\def\lst@texcs{#1}}
\lst@AddToHook{SetLanguage}{\let\lst@texcs\@empty}
% \end{macrocode}
% \begin{macrocode}
\lst@AddToHook{Output}
{\lst@ifmode\else \ifx\lst@lastother\lst@backslash %
\expandafter\lst@IfOneOf\the\lst@token\relax \lst@texcs %
{\let\lst@thestyle\lst@keywordstyle}%
{\let\lst@thestyle\relax}%
\fi \fi}
% \end{macrocode}
% \end{aspect}
% \begingroup
% \begin{macrocode}
%</tex>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Compiler directives in C}
%
% \begingroup
% \begin{macrocode}
%<*c>
% \end{macrocode}
% \endgroup
% \begin{aspect}{cdirectives}
% First some usual stuff:
% \begin{macrocode}
\lst@Aspect{cdirectives}
{\lst@MakeKeywordArg{,#1}\let\lst@cdirectives\lst@arg}
\lst@AddToHook{SetLanguage}{\let\lst@cdirectives\relax}
% \end{macrocode}
% If the user has defined directives, we redefine the character |#| (but save the old meaning before):
% \begin{macrocode}
\lst@AddToHook{SelectCharTable}
{\ifx\lst@cdirectives\relax\else %
\lccode`\~=`\#\lowercase{\let\lsts@CCD~\def~}%
{\lst@ifmode\else %
% \end{macrocode}
% We enter 'directive mode' only if we are in column 1.
% Note that 'directive mode' is |\lst@egroupmode| without setting |\lst@ifmode| true.
% \begin{macrocode}
\@tempcnta\lst@column %
\advance\@tempcnta\lst@length %
\advance\@tempcnta-\lst@pos %
\ifnum\@tempcnta=\z@ %
\lst@EnterMode{\lst@egroupmode}%
{\expandafter\lst@lAddTo\expandafter\lst@keywords%
\expandafter{\lst@cdirectives}}%
\fi %
\fi %
\ifnum\lst@mode=\lst@egroupmode %
{\lst@keywordstyle\lsts@CCD\lst@PrintToken}%
\else \lsts@CCD %
\fi}%
\fi}
% \end{macrocode}
% \end{aspect}
% \begingroup
% \begin{macrocode}
%</c>
% \end{macrocode}
% \endgroup
%
%
% \subsection{PODs in Perl}
%
% \begingroup
% \begin{macrocode}
%<*perl>
% \end{macrocode}
% \endgroup
% \begin{aspect}{printpod}
% We begin with two user commands, which I introduced after communication with \lsthelper{Michael Piotrowski}{mxp@linguistik.uni-erlangen.de}{1997/11/11}{\lstprintpodtrue/false}.
% \begin{macrocode}
\lst@Aspect{printpod}[t]{\lstKV@SetIfKey\lst@ifprintpod{#1}}
\lstset{printpod=false}% init
% \end{macrocode}
% \end{aspect}
%
% \begin{macro}{\lst@PODmode}
% Define a new mode and use |\global| since we are (possibly) in a driver file and thus inside a group.
% \begin{macrocode}
\global\lst@NewMode\lst@PODmode
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@PODcut}
% We'll need the active character string |cut|:
% \begin{macrocode}
\lst@MakeActive{cut}\global\let\lstCC@PODcut\lst@arg %
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@ProcessPOD}
% And now the POD character class; only |=| will belong to it.
% If we are in column 1 \ldots
% \begin{macrocode}
\gdef\lstCC@ProcessPOD{%
\let\lstCC@next\relax %
\@tempcnta\lst@column %
\advance\@tempcnta\lst@length %
\advance\@tempcnta-\lst@pos %
\ifnum\@tempcnta=\z@ %
% \end{macrocode}
% and if we are already in POD mode, we either end it or proceed according to whether next characters are |cut| or not.
% \begin{macrocode}
\ifnum\lst@mode=\lst@PODmode %
\def\lstCC@next{\lst@IfNextChars\lstCC@PODcut %
{\lstCC@ProcessEndPOD}%
{\lsts@POD\lst@eaten}}%
\else %
% \end{macrocode}
% If we are in column 1 and not in POD mode, we either start a usual comment or drop the output.
% \begin{macrocode}
\lst@ifprintpod %
\lstCC@BeginComment\lst@PODmode %
\else %
\lst@BeginDropOutput\lst@PODmode %
\fi %
\let\lstCC@next\lsts@POD %
\fi %
\fi \lstCC@next}%
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstCC@ProcessEndPOD}
% If the character behind |=cut| is neither |^^M| nor |^^J|, we don't end the POD.
% \begin{macrocode}
\gdef\lstCC@ProcessEndPOD#1{%
\let\lstCC@next\lstCC@ProcessEndPOD@ %
\ifnum`#1=`\^^M\else \ifnum`#1=`\^^J\else %
\def\lstCC@next{\lsts@POD\lst@eaten#1}%
\fi \fi %
\lstCC@next}
% \end{macrocode}
% The ending actions depend on |\lst@ifprintpod|: Print |=cut| (or not) and end the POD.
% \begin{macrocode}
\gdef\lstCC@ProcessEndPOD@{%
\lst@ifprintpod \lsts@POD\lst@eaten\lst@PrintToken \fi %
\lst@LeaveMode}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</perl>
% \end{macrocode}
% \endgroup
%
%
% \subsection{Special use of \texttt{\#} in Perl}
%
% \begingroup
% \begin{macrocode}
%<*perl>
% \end{macrocode}
% \endgroup
% \begin{macro}{\lstCC@SpecialUseAfter}
% We need |#| not to begin a comment in Perl if it follows |$|.
% We'll define a special use of |#| after |$| via |\lstCC@SpecialUseAfter{\$}{\#}{\lstCC@ProcessOther\#}| where the third argument is executed coming to |$#|.
% Note that the submacro gets two of the three arguments.
% \begin{macrocode}
\gdef\lstCC@SpecialUseAfter#1{%
\lccode`\~=`#1\lccode`\/=`#1\lowercase{\lstCC@SpecialUseAfter@~/}}
% \end{macrocode}
% We save the old meaning of the first character (|$|) and redefine it to check for the character |#3|.
% \begin{macrocode}
\gdef\lstCC@SpecialUseAfter@#1#2#3#4{%
\expandafter\let\csname lsts@SUA#2\endcsname#1%
\def#1##1{%
\ifnum`##1=`#3%
\def\lstCC@next{\csname lsts@SUA#3\endcsname\relax #4}%
\else %
\def\lstCC@next{\csname lsts@SUA#3\endcsname ##1}%
\fi %
\lstCC@next}}
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
%</perl>
% \end{macrocode}
% \endgroup
%
%
% \section{Epilogue}
%
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% Most initialization has already been done, see all |% init| marked lines.
% Here is more:
% \begin{macrocode}
\lstset{labelsep=5pt,sensitive=true}
\lstdefinelanguage{}{}
\lstdefinestyle{}
{basicstyle={},%
keywordstyle=\bfseries,nonkeywordstyle={},%
commentstyle=\itshape,stringstyle={},%
labelstyle={},labelstep=0}
\lst@mode=\z@
\lstset{language={},style={}}
% \end{macrocode}
% Finally we load compatibility mode, a patch file and the configuration file.
% \begin{macrocode}
\@ifundefined{lst@0.17}{}{\input{lst017.sty}}
\InputIfFileExists{lstpatch.sty}{}{}
\InputIfFileExists{listings.cfg}{}{}
% \end{macrocode}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
% \endgroup
%
%
% \section{Interfaces to other packages}
%
%
% \subsection{Compatibility mode}
%
% \begingroup
% \begin{macrocode}
%<*0.17>
% \end{macrocode}
% \endgroup
% We give a warning first.
% \begin{macrocode}
\message{^^J%
*** You have requested compatibility mode `0.17'.^^J%
*** This mode is for documents created for version 0.17 only.^^J%
*** I T\@spaces I S\@spaces N O T\@spaces F U L L Y\@spaces %
C O M P A T I B L E.^^J^^J}
% \end{macrocode}
%
%
% \paragraph{Language names.}
%
% Since some programming languages changed their names, we define aliases here.
% \begin{macrocode}
\lstalias[]{blank}[]{}
\lstalias{cpp}{C++}
\lstalias[vc]{C++}[Visual]{C++}
\lstalias{comal}{Comal 80}
\lstalias{modula}{Modula-2}
\lstalias{oberon}{Oberon-2}
\lstalias[]{pxsc}[XSC]{Pascal}
\lstalias[]{tp}[Borland6]{Pascal}
\lstalias{pli}{PL/I}
% \end{macrocode}
%
%
% \paragraph{User commands.}
%
% Old commands in terms of keys:
% \begin{macrocode}
\def\inputlisting{%
\@ifnextchar[\inputlisting@{\inputlisting@[1,999999]}}
\def\inputlisting@[#1,#2]{\lstinputlisting[first=#1,last=#2]}
% \end{macrocode}
% \begin{macrocode}
\newcommand\selectlisting[2][]{\lstset{language=[#1]#2}}
\def\listingtrue{\lstset{print=true}}
\def\listingfalse{\lstset{print=false}}
\def\tablength#1{\lstset{tabsize=#1}}\tablength{4}% init
\def\keywordstyle#1{\lstset{keywordstyle={#1}}}
\def\commentstyle#1{\lstset{commentstyle={#1}}}
\def\stringstyle#1{\lstset{stringstyle={#1}}}
\def\labelstyle#1{\lstset{labelstyle={#1}}}
\newcommand\stringizer[2][d]{\lstset{stringizer=[#1]#2}}
\def\blankstringtrue{\lstset{blankstring=true}}
\def\blankstringfalse{\lstset{blankstring=false}}
\def\spreadlisting#1{\lstset{spread={#1}}}
\def\prelisting#1{\def\lst@pre{#1}}
\def\postlisting#1{\def\lst@post{#1}}
\def\normallisting{%
\lstset{style={},spread=\z@,pre={},post={}}}
\def\keywords#1{\lstset{keywords={#1}}}
\def\morekeywords#1{\lstset{morekeywords={#1}}}
\def\sensitivetrue{\lstset{sensitive=true}}
\def\sensitivefalse{\lstset{sensitive=false}}
\let\lst@stringblank\textvisiblespace
% \end{macrocode}
% We define the (new) old environment.
% \begin{macrocode}
\lst@Environment{listing}[1][]\is
{\ifx\@empty#1\@empty\else \lst@AddToLOL{#1}{}\fi}
{}
% \end{macrocode}
%
%
% \paragraph{Comments.}
%
% The implementation of old comment commands in terms of the new ones is all the same:
% If the last argument is empty, we remove the comment; otherwise we execute the new key with correct syntax.
% \begin{macrocode}
\def\DeclareCommentLine#1\relax{%
\ifx\@empty#1\@empty %
\let\lst@DefCL\relax %
\else %
\lstset{commentline=#1}%
\fi}
% \end{macrocode}
% \begin{macrocode}
\def\DeclareSingleComment#1 #2\relax{%
\ifx\@empty#2\@empty %
\let\lst@DefSC\relax \let\lst@DefDC\relax %
\else %
\lstset{singlecomment={#1}{#2}}%
\fi}
% \end{macrocode}
% \begin{macrocode}
\def\DeclarePairedComment#1\relax{
\ifx\@empty#1\@empty %
\let\lst@DefSC\relax \let\lst@DefDC\relax %
\else %
\lstset{singlecomment={#1}{#1}}%
\fi}
% \end{macrocode}
% \begin{macrocode}
\def\DeclareNestedComment#1 #2\relax{%
\ifx\@empty#2\@empty %
\let\lst@DefSC\relax \let\lst@DefDC\relax %
\else %
\lstset{nestedcomment={#1}{#2}}%
\fi}
% \end{macrocode}
% \begin{macrocode}
\def\DeclareDoubleComment#1 #2 #3 #4\relax{%
\ifx\@empty#4\@empty %
\let\lst@DefSC\relax \let\lst@DefDC\relax %
\else %
\lstset{doublecomment={#1}{#2}{#3}{#4}}%
\fi}
% \end{macrocode}
% \begingroup
% \begin{macrocode}
%</0.17>
% \end{macrocode}
% \endgroup
%
%
% \subsection{\textsf{fancyvrb}}
%
% \lsthelper{Denis Girou}{Denis.Girou@idris.fr}{1998/07/26}{fancyvrb} asked whether \textsf{fancyvrb} and \textsf{listings} could work together.
% Here's the first try.
% \begingroup
% \begin{macrocode}
%<*kernel>
% \end{macrocode}
% \endgroup
% \begin{aspect}{fancyvrb}
% We set the boolean and input the interface file (first time only).
% \begin{macrocode}
\lst@Aspect{fancyvrb}[t]{%
\lstKV@SetIfKey\lst@iffancyvrb{#1}%
\lstfancyvrb@}
\def\lstfancyvrb@{\input{lstfvrb.sty}\lstfancyvrb@}
% \end{macrocode}
% \end{aspect}
% \begingroup
% \begin{macrocode}
%</kernel>
% \end{macrocode}
%
% \begin{macrocode}
%<*fancyvrb>
% \end{macrocode}
% We will use |@|-protected names:
% \begin{macrocode}
\begingroup \makeatletter
% \end{macrocode}
% \endgroup
% \begin{macro}{\lstFV@Def}
% \begin{macro}{\lstFV@Let}
% \begin{macro}{\lstFV@Use}
% \begin{macro}{\lstFV@ECUse}
% \begin{macro}{\lstFV@Tabulator}
% \begin{macro}{\lstFV@Space}
% \begin{macro}{\lstFV@Stringizer@}
% These are copies of the |\lstCC@|\ldots\ macros, but all catcode changes are removed.
% \begin{macrocode}
\gdef\lstFV@Def#1{\lccode`\~=#1\lowercase{\def~}}%
\gdef\lstFV@Let#1{\lccode`\~=#1\lowercase{\let~}}%
% \end{macrocode}
% \begin{macrocode}
\gdef\lstFV@Use#1#2#3{%
\ifnum#2=\z@ %
\expandafter\@gobbletwo %
\else %
\lccode`\~=#2\lowercase{\def~}{#1#3}%
\fi %
\lstFV@Use#1}%
% \end{macrocode}
% \begin{macrocode}
\gdef\lstFV@ECUse#1#2{%
\ifnum`#2=\z@ %
\expandafter\@gobbletwo %
\else %
\ifnum\catcode`#2=\active %
\lccode`\~=`#2\lccode`\/=`#2\lowercase{\lstCC@ECUse@#1~/}%
\else %
\lccode`\~=`#2\lowercase{\def~}{#1#2}%
\fi %
\fi %
\lstFV@ECUse#1}%
% \end{macrocode}
% \begin{macrocode}
\gdef\lstFV@Tabulator#1{\lstFV@Let{#1}\lstCC@ProcessTabulator}%
\gdef\lstFV@Space#1{\lstFV@Let{#1}\lstCC@ProcessSpace}%
% \end{macrocode}
% \begin{macrocode}
\gdef\lstFV@Stringizer@#1#2{%
\ifx\@empty#2%
\expandafter\@gobbletwo %
\else %
\lccode`\~=`#2\lccode`\/=`#2%
\lowercase{%
\expandafter\let\csname lsts@s/\endcsname~%
\def~{#1/}}%
\fi %
\lstFV@Stringizer@#1}%
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}\end{macro}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lstFV@FancyVerbFormatLine}
% This macro will be assigned to |\FancyVerbFormatLine|: We convert the argument and typeset it.
% \begin{macrocode}
\gdef\lstFV@FancyVerbFormatLine#1{%
\let\lstenv@arg\@empty\lstenv@AddArg{#1}%
\lstenv@arg \lst@PrintToken\lst@EOLUpdate}%
% \end{macrocode}
% \begin{TODO}
% This old macro is overwritten below.
% \end{TODO}
% \end{macro}
%
% \begin{macro}{\lstfancyvrb@}
% The command assigns some new macros (if it's not already done).
% \begin{macrocode}
\gdef\lstfancyvrb@{%
\ifx\FV@VerbatimBegin\lstFV@VerbatimBegin\else %
\let\lstFV@OldVB\FV@VerbatimBegin %
\let\lstFV@OldVE\FV@VerbatimEnd %
\let\FV@VerbatimBegin\lstFV@VerbatimBegin %
\let\FV@VerbatimEnd\lstFV@VerbatimEnd %
\fi %
% \end{macrocode}
% And we assign the correct |\FancyVerbFormatLine| macro.
% \begin{macrocode}
\lst@iffancyvrb %
\ifx\FancyVerbFormatLine\lstFV@FancyVerbFormatLine\else %
\let\lstFV@FVFL\FancyVerbFormatLine %
\let\FancyVerbFormatLine\lstFV@FancyVerbFormatLine %
\fi %
\else %
\ifx\lstFV@FVFL\@undefined\else %
\let\FancyVerbFormatLine\lstFV@FVFL %
\fi %
\fi}%
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstFV@VerbatimBegin}
% We initialize things if necessary.
% \begin{macrocode}
\gdef\lstFV@VerbatimBegin{%
\lstFV@OldVB %
\ifx\FancyVerbFormatLine\lstFV@FancyVerbFormatLine %
\lst@DontEscapeToLaTeX %
\let\smallbreak\relax \let\normalbaselines\relax %
\let\lst@prelisting\relax \let\lst@postlisting\relax %
\def\lst@firstline{1}\def\lst@lastline{999999}%
% \end{macrocode}
% \begin{macrocode}
\let\lstCC@Use\lstFV@Use %
\let\lstCC@ECUse\lstFV@ECUse %
\let\lstCC@Tabulator\lstFV@Tabulator %
\let\lstCC@Space\lstFV@Space %
\let\lstCC@Stringizer@\lstFV@Stringizer@ %
% \end{macrocode}
% \begin{macrocode}
\def\lst@next{%
\lst@Init\relax %
\everypar{}\global\let\lst@NewLine\relax}%
\expandafter\lst@next %
\fi}%
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstFV@VerbatimEnd}
% A (particular) box and macro must exist after |\lst@DeInit|.
% We store them globally.
% \begin{macrocode}
\gdef\lstFV@VerbatimEnd{%
\ifx\FancyVerbFormatLine\lstFV@FancyVerbFormatLine %
\global\setbox\lstFV@gtempboxa\box\@tempboxa %
\global\let\@gtempa\FV@ProcessLine %
\lst@DeInit %
\let\FV@ProcessLine\@gtempa %
\setbox\@tempboxa\box\lstFV@gtempboxa %
\fi %
\lstFV@OldVE}%
% \end{macrocode}
% \begin{macrocode}
\newbox\lstFV@gtempboxa %
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lstFV@FancyVerbFormatLine}
% A slightly different definition now: |\lstenv@AddArg{#1}| has been replaced by |\lstFV@Convert#1@|.
% The '@' terminates the input |#1|.
% \begin{macrocode}
\gdef\lstFV@FancyVerbFormatLine#1{%
\let\lst@arg\@empty\lstFV@Convert#1@%
\lst@arg \lst@PrintToken\lst@EOLUpdate}%
% \end{macrocode}
% And this macro is to be defined right now.
% \begin{macrocode}
\gdef\lstFV@Convert{%
\@ifnextchar\bgroup{\lstFV@Convert@Arg}{\lstFV@Convert@}}%
% \end{macrocode}
% Coming to a begin group character ('\{' with catcode 1) we convert the and add the conversion together with group delimiters to |\lst@arg|.
% We also add |\lst@PrintToken|, which prints all collected characters before we forget them.
% Finally we continue the conversion.
% \begin{macrocode}
\gdef\lstFV@Convert@Arg#1{%
{\let\lst@arg\@empty \lstFV@Convert#1@\global\let\@gtempa\lst@arg}%
\expandafter\lst@lAddTo\expandafter\lst@arg\expandafter{%
\expandafter{\@gtempa\lst@PrintToken}}%
\lstFV@Convert}%
% \end{macrocode}
% If we haven't found a |\bgroup|, we look whether we've found the end of the input.
% If not, we convert one token ((non)active character or control sequence) and continue conversion.
% \begin{macrocode}
\gdef\lstFV@Convert@#1{%
\ifx @#1\else %
\expandafter\lstFV@Convert@@\string#1\@empty\@empty\relax{#1}%
\expandafter\lstFV@Convert %
\fi}%
% \end{macrocode}
% |\string#1| from above expands to 'backslash + some characters' if |#1| is a control sequence.
% In this case the argument |#2| here equals not |\@empty|.
% The other implication: If |#2| equals |\@empty|, |\string#1| necessarily expanded to a single character, which can't be a control sequence (|\escapechar>=0| granted).
% Thus, we add an active character if and only if the second argument equals |\@empty|, and we append the control sequence otherwise.
% In the latter case we must print all preceding characters (and all the lost space).
% \begin{macrocode}
\gdef\lstFV@Convert@@#1#2#3\relax#4{%
\ifx\@empty#2%
\lccode`\~=`#4\lowercase{\lst@lAddTo\lst@arg~}%
\else %
\lst@lAddTo\lst@arg{\lst@UseLostSpace\lst@PrintToken#4}%
\fi}%
% \end{macrocode}
% \end{macro}
% \begingroup
% \begin{macrocode}
\endgroup %
% \end{macrocode}
% \begin{macrocode}
%</fancyvrb>
% \end{macrocode}
% \endgroup
%
%
% \begingroup\small
% \section{History}
% Only major changes after version 0.15 are listed here.
% Previous changes are still present in the \texttt{.dtx}-file.
% Introductory version numbers of the user commands are listed in the user's guide.
% \renewcommand\labelitemi{--}
% \begin{itemize}
% \iffalse
% \item[0.1] from 1996/03/09
% \item test version to look whether package is possible or not
% \item[0.11] from 1996/08/19
% \item additional blank option (= language)
% \item alignment improved by rewriting some macros
% \item[0.12] from 1997/01/16
% \item nearly 'perfect' alignment now
% \item[0.13] from 1997/02/11
% \item additional languages: Eiffel, Fortran 90, Modula-2, Pascal XSC
% \item load on demand: language specific macros moved to driver files
% \item comments are declared now and not implemented for each language again (this makes the \TeX{} sources easier to read)
% \item[0.14] from 1997/02/18
% \item user's guide rewritten
% \item implementation guide uses macro environment from the doc package
% \item (non) case sensitivity implemented, e.g.\ Pascal is not
% \item multiple stringizer implemented, i.e.\ Modula-2 handles both string types: quotes and double quotes
% \item comment declaration is user-accessible now
% \item package compatible to \verb!german.sty! now
% \item[0.15] from 1997/04/18
% \item additional languages: Java, Turbo Pascal
% \item package renamed from listing.dtx to listings.dtx, since there is already a package named listing
% \fi
% \item[0.16] from 1997/06/01
% \iffalse
% \item changed '$<$' to '$>$' in \verb!\lst@SkipUptoFirst!
% \item bug removed: \verb!\lst@Init! must be placed before \verb!\lst@SkipUptoFirst!
% \fi
% \item listing environment rewritten
% \item[0.17] from 1997/09/29
% \item |\spreadlisting| works correct now (e.g.\ page numbers move not right any more)
% \item speed up things (quick 'if parameter empty', all |\long| except one removed, faster \verb!\lst@GotoNextTabStop!, etc.)
% \item alignment of wide other characters improved (e.g.\ $==$)
% \iffalse
% \item many new languages: Ada, Algol, Cobol, Comal 80, Elan, Fortran 77, Lisp, Logo, Matlab, Oberon, Perl, PL/I, Simula, SQL, \TeX{}
% \fi
% \item[pre-0.18] from 1998/03/24 (unpublished)
% \item bug concerning |\labelstyle| removed (now oldstylenum example works)
% \item experimental implementation of character classes
% \item[0.19] from 1998/11/09
% \item character classes and \lst-aspects (new) seem to be the ultimate, all became implemented in these terms
% \item \lst-aspects became an application (new) to \textsf{keyval} and hooks
% \item \textsf{fancyvrb} support
% \end{itemize}
%
%
% \setcounter{IndexColumns}{2}
% \PrintIndex
%
%
% \Finale
%
\endinput