% \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} % % \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 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 % % \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} % % \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} % % \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} % % \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} % % \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} % % \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 % % \lst@InfoInfo{New aspect `#1'}% \else % % \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}{% % \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}{% % \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} % % \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} % % \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} % % \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 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 % % \lst@InfoInfo{\expandafter\string % % \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 to proceed without changing the language.}}% % \end{macrocode} % Otherwise we execute the hook and select the language. % \begin{macrocode} {\lsthk@SetLanguage % % \lst@InfoInfo{\expandafter\string % % \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} % % \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} % % \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} % % \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} % % \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 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} % % \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}}% {% % \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 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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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 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 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} % % \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} % % \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} % % \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} % % \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} % % \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}{}{% % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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} % % \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