% \iffalse
%<*driver>
\documentclass{ltxdoc}

\usepackage[c,cpp,pascal,fortran]{listings}
\EnableCrossrefs         
\CodelineIndex
\OldMakeindex     % used for MakeIndex pre v2.9

\begin{document}
    \DocInput{listings.dtx}
\end{document}
%</driver>
%
% listings package for LaTeX2e
% (w)(c) 1996-1997 Carsten Heinz, all rights reserved.
% 
%<+package>\NeedsTeXFormat{LaTeX2e}
%<+package>\ProvidesPackage{listings}[1997/04/10 v0.15 by Carsten Heinz]
% \fi
%
% \CheckSum{1477}
% \DoNotIndex{\@ifundefined,\@tempa,\ }
% \DoNotIndex{\[,\{,\},\],\1,\2,\3,\4,\5,\6,\7,\8,\9,\0}
% \DoNotIndex{\`,\,,\!,\#,\$,\&,\',\(,\),\+,\.,\:,\;,\<,\=,\>,\?,\_}
% \DoNotIndex{\active,\advance,\begin,\backslash,\baselineskip}
% \DoNotIndex{\begingroup,\bfseries,\bgroup,\catcode,\chardef}
% \DoNotIndex{\closein,\csname,\def,\do,\edef,\egroup,\else,\empty}
% \DoNotIndex{\end,\endcsname,\endgroup,\expandafter,\fi,\gdef}
% \DoNotIndex{\global,\hbox,\hss,\if,\ifcat,\ifeof,\ifnum,\ifx}
% \DoNotIndex{\ignorespaces,\input,\itshape,\let,\long,\loop,\lst@}
% \DoNotIndex{\makeatletter,\makeatother,\message,\newcommand}
% \DoNotIndex{\newcount,\newdimen,\newif,\newread,\next,\noindent}
% \DoNotIndex{\openin,\par,\read,\relax,\repeat,\space,\smallbreak}
% \DoNotIndex{\string,\test,\ttfamily,\vskip,\vspace}
%
% \title{{LISTINGS.DTX} Version {0.15}}
% \author{{\copyright} 1996--1997 by Carsten Heinz}
% \date{}
% \maketitle
% \tableofcontents
%
%
% \section{User's guide}
%
%
% \subsection{Introduction}
%
% You have a problem? You wanna typeset C, C++, Eiffel, Fortran 90,
% Java, Modula-2, Pascal, Pascal XSC or Turbo Pascal code within
% \LaTeXe{} like
%     \cpplisting   \inputlisting{listing1.cpp}
% \noindent or
%     \pascallisting\inputlisting{listing2.pas}
% Obviously the verbatim environment doesn't fit. You might use the
% tabbing environment or something like that. But you have to mark all
% keywords yourself and doing the indention is also a heavy work. But
% the most striking disadvantage is that you can't run your \LaTeXe-file
% through your C, C++, Eiffel or whatever else compiler.
% 
% Fortunately there is another possibility. You might use a cross
% compiler, e.g.\ you run a special compiler on your Pascal source
% code to get a \TeX-file with marked keywords, etc. Then \TeX{}
% produces a pretty output (usage of a well-designed cross compiler
% granted). If your sources change, you would have to rerun the cross
% compiler to get your \TeX-file right and have to compile this to get
% your document. Again and again.
%
% By now these days have gone. The listings package goes around this by
% reading the source code directly. Comments, strings and keywords can
% be typeset in different styles as shown by the examples above. The
% indention is taken from the sources. Hence, the programmer is
% responsible for writing 'readable' code. The package only helps to
% present it.
%
% This package is surely not the final utility for typesetting
% listings. May be it's a matter of pureness whether to use a cross
% compiler or the listings package. Hope you join it and help to get
% this tool more powerful. Please report all errors and offer
% improvements!
% 
%
% \subsection{Installation}
%
% The listings package consists of following files:
% \begin{verbatim}
%    listings.dtx    listings.ins     listings.dvi
%    listing1.cpp    listing2.pas     listing3.cpp
%    testfile.pas
%    listings.sty    lstblank.sty     lstc.sty
%    lstcpp.sty      lsteiffel.sty    lstfortran.sty
%    lstjava.sty     lstmodula.sty    lstpascal.sty
%    lstpxsc.sty     lsttp.sty\end{verbatim}
% The exact names are system dependent. It doesn't matter, if you only
% have the .dtx- and .ins-file. In that case run \verb!listings.ins!
% through \TeX{} and then \verb!listings.dtx!. You will get all the
% other files. To install the package copy all eleven .sty-files to a
% directory searched by \TeX{}. You might want to create a
% subdirectory. The installation is complete.
%
% \textbf{Important note:} All files mentioned are distributed freely.
% You are not allowed to take money for the distribution or use of
% these files, except for a nomial charge for copying etc.
% The files are distributed without any warranty; without even the
% implied warranty of merchantability or fitness for a particular
% purpose.
% You are not allowed to change one of the files, except using a
% clearly different filename.
%
% \textbf{Trademarks} appear throughout this documentation without any
% trademark symbol. So you can't assume that a name is not trademarked.
% There is no intention of infringement. The usage is to the benefit
% of the trademark owner.
%
%
% \subsection{Typesetting a listing}
% \DescribeMacro\inputlisting
% The main command for this purpose is \cs{inputlisting}. The syntax
% is
% \begin{verbatim}
%    \inputlisting[FIRST,LAST]{WHOLE FILENAME}\end{verbatim}
% where \verb![FIRST,LAST]! is optional and determines the range of
% lines to typeset, but at least one line will be printed. The default
% range is $[1,999999]$. If you specify negative lines or an empty
% range, for example, you won't get any warning. There is no default
% extension, so you must specify the whole filename. The example
% \begin{verbatim}
%    \inputlisting[3,10]{testfile.pas}\end{verbatim}
% would print lines 3,4,\ldots,10 of \verb!testfile.pas!.
%
% \DescribeEnv{listing}
% There is also a listing environment. It typesets the source code
% enclosed within \verb!\begin{listing}! and \verb!\end{listing}!.
% If the source code starts right after \verb!\begin{listing}! you will
% get a bad output, since that line has not the correct position.
% Additionally the source preceding \verb!\end{listing}! is not output
% and the rest of the line is not typeset by \TeX. You may don't like
% this, but the lines
% \begin{verbatim}
%\fortranlisting
%\begin{listing}
%* This is a test for the listing environment
%C and not considered to be an example for
%   ! Fortran!
%      PROGRAM example
%      ...
%\end{listing}\end{verbatim}
% result in
%    \fortranlisting
% \iffalse
%<*envtest>
% \fi
%    \begin{listing}
* This is a test for the listing environment
C and not considered to be an example for
   ! Fortran!
      PROGRAM example
      ...
%    \end{listing}
% \iffalse
%</envtest>
% \fi
%
% \DescribeMacro\listingfalse
% \DescribeMacro\listingtrue
% Since typesetting listings with this package is possibly slow,
% you can suppress the output with \cs{listingfalse}. Afterwards this
% package only prints the name of the source like
%     \listingfalse\inputlisting{testfile.pas}\listingtrue
% \cs{listingtrue} reverses the effect.
% 
% \DescribeMacro\tablength
% If you use tabulators in your source codes, you have to tell this
% package the number of characters between two tabulator stops.
% Default value is 4. Changes are made by, e.g.,\ 
% \begin{verbatim}
%    \tablength{8}\end{verbatim}
% i.e. tabulator stops are set at the columns 1, 9, 17, 25 {\ldots}
% Negative values are prohibited. They won't confuse this package,
% since it gives an error message and proceeds with the old value of
% tablength.
%
% \DescribeMacro\prelisting
% \DescribeMacro\postlisting
% The commands \cs{prelisting} and \cs{postlisting} have one argument
% each and can be used to add something right before a listing starts
% or after it ends, e.g.\ \verb!\prelisting{\bigbreak}! will lead to
% an empty line between a listing and the text above (if on the same
% page).  A useful application of the pre-post-mechanism is the
% selection of fontsize and / or the change of textwidth. The C++
% source line
%     \cpplisting   \inputlisting{listing3.cpp}
% \noindent gives rise to an overfull \verb!\hbox!. You should use
% \begin{verbatim}
%    \prelisting{\footnotesize % select new fontsize
%                \advance\textwidth by 1in %spread textwidth by 1 inch
%                \advance\leftskip by -0.5in   % add 0.5 inch
%                \advance\rightskip by -0.5in} % on each side
%    \postlisting{} % nothing to do (default)\end{verbatim}
% or something similar and get
%     \prelisting{\footnotesize \advance\textwidth by 1in %
%         \advance\leftskip by -0.5in \advance\rightskip by -0.5in}
%     \cpplisting   \inputlisting{listing3.cpp}
%     \normallisting
% Note: This is a 'brute force' example. The change of the fontsize is
% harmless, but there is no guarantee that the changes to textwidth
% and the skips work with all of \LaTeXe{}. Be careful and report
% success and failure!
%
%
% \subsection{Output styles}
% You have some possibilities to change how the output looks like.
%
% \DescribeMacro\keywordstyle
% \DescribeMacro\commentstyle
% \DescribeMacro\stringstyle
% By default keywords are typeset bold, comments in italic shape and
% strings using no special style. You can change this with the
% commands \cs{keywordstyle}, \cs{commentstyle} and \cs{stringstyle},
% e.g.
% \begin{verbatim}
%    \keywordstyle{\bfseries\itshape} % bold and italic
%    \commentstyle{\tt\small}         % LaTeX 2.09 typewriter, small
%    \stringstyle{\ttfamily}          % typewriter\end{verbatim}
% will typeset the first example of the introduction as follows
%     \keywordstyle{\bfseries\itshape} \commentstyle{\tt\small}
%     \stringstyle{\ttfamily}
%     \cpplisting \inputlisting{listing1.cpp} \normallisting
% \DescribeMacro\blankstringtrue
% \DescribeMacro\blankstringfalse
% \makeatletter\let\stringblank=\lst@string@blank\makeatother
% Once again blank spaces of a string have been printed \stringblank.
% Suppress this by using \cs{blankstringtrue} and switch to default
% with \cs{blankstringfalse}.
%
% \DescribeMacro\normallisting
% Changes made by the commands above are reset by \cs{normallisting}
% (there are no arguments): Keywords are typeset bold, comments in
% italic shape, stringstyle and pre- and postlisting are empty and
% blank spaces in strings are printed \stringblank.
% The selected programming language is not affected.
%
%
% \subsection{Selecting a language}
% There are two ways to do this. When you load the package in the
% preamble, you can choose a language by one of the options
% \begin{verbatim}
%   blank  c  cpp  eiffel  fortran  java  modula  pascal  pxsc  tp\end{verbatim}
% e.g.\ 
% \begin{verbatim}
%    \usepackage[c,cpp,pascal]{listings}\end{verbatim}
% loads all definitions for C, C++ and Pascal listings, but the last
% specified language is selected. Default option and language is blank:
% no keywords and no comments are detected (unless additional keywords
% are specified, see section \ref{sOtherLanguages}).
%
% \iffalse
% \DescribeMacro\blanklisting \DescribeMacro\clisting
% \DescribeMacro\cpplisting \DescribeMacro\eiffellisting
% \DescribeMacro\fortranlisting \DescribeMacro\javalisting
% \DescribeMacro\modulalisting \DescribeMacro\pascallisting
% \DescribeMacro\pxsclisting \DescribeMacro\tplisting
% \fi
% In your document you can change the language with the commands
% \begin{verbatim}
%    \blanklisting    \clisting         \cpplisting
%    \eiffellisting   \fortranlisting   \javalisting
%    \modulalisting   \pascallisting    \pxsclisting
%    \tplisting\end{verbatim}
% e.g.\ 
% \begin{verbatim}
%    \inputlisting[3,10]{testfile.pas}
%    \cpplisting                 % switch to C++
%    \inputlisting{testfile.cpp}\end{verbatim}
% If you haven't used the corresponding option, the languages are loaded
% on demand.
%
% \noindent Note: Language selection is global, i.e.\ the language is
% changed in outer blocks by selecting another language in an inner
% group.
%
%
% \subsection{Other languages}\label{sOtherLanguages}
%
% You have some possibilities to adapt this package to other languages.
% For our purpose here the main characteristics of a language are
% keywords, comments and strings.
%
% \DescribeMacro\morekeywords
% With the blank option you can produce verbatim-like output.
% But it is also possible to add your own keywords. Use the command
% \cs{morekeywords} like
% \begin{verbatim}
%    \morekeywords{maxreal,minreal} % add these keywords
%    \morekeywords{zero,MAXINT}     % add also\end{verbatim}
% \DescribeMacro\keywords
% If you want the old keywords deleted, use \cs{keywords} instead. After
% \begin{verbatim}
%    \keywords{one,two,three,four,five,six,seven,eight,nine,ten,%
%        eleven,twelve}\end{verbatim}
% exactly these twelve keywords are present. The remark character \%
% at the end of the first line is essential! Otherwise one keyword
% would be '\stringblank\verb!eleven!', but a keyword must begin with
% a letter.
%
% \DescribeMacro\sensitivetrue
% \DescribeMacro\sensitivefalse
% Some languages are case sensitive, others are not. You can select
% this with \cs{sensitivetrue} and \cs{sensitivefalse}, respectively.
% This package will then use the right keyword test.
%
% \DescribeMacro\stringizer
% The command \cs{stringizer} changes the character, which begins and
% ends a string. If your parameter consists of several characters,
% each character can start a string. But the string must be terminated
% with the same character. Using a letter, a digit or the underbar as
% stringizer will not work. The Modula-2 option defines the stringizer
% by
% \begin{verbatim}
%    \begingroup
%    \catcode`\"=12
%    \stringizer{'"}
%    \endgroup\end{verbatim}
% The catcode is locally changed for compatibility with
% \verb!german.sty!. The double quote is defined active there, but
% when we input a listing the double quote will have catcode 12
% (=other).
%
% Let's come to comments. For our purpose a 'comment line' is a comment,
% which starts with a character sequence and goes upto the end of a
% line. 'Comments' start and end with given character sequences.
% Comment lines need not to begin at the first column and comments
% can start and end wherever you want.
%
% \DescribeMacro\DeclareCommentLine
% \cs{DeclareCommentLine} has one parameter, which is terminated by
% \cs{relax}, i.e.\ 
% \begin{verbatim}
%    \DeclareCommentLine //\relax\end{verbatim}
% is legal. The parameter is a (nearly) arbitrary character sequence,
% which separates a comment line. Using a letter, a digit or the
% underbar will not work. And: When we input a listing, the characters
% must have the same category codes. Refer section
% \ref{SpecialCharacters} and \ref{ssSpecialCharacters}.
% If you don't want any comment lines, let the parameter empty, but
% don't forget the \cs{relax}!
%
% \DescribeMacro\DeclareSingleComment
% \DescribeMacro\DeclareDoubleComment
% \DescribeMacro\DeclareNestedComment
% Three types of comments are supported: \textbf{single} for languages
% with one kind of comment, e.g.\ C or C++; \textbf{double} for
% languages with two kinds of comments, e.g.\ Pascal comments enclosed
% within \verb!(*! and \verb!*)! and within \verb!{! and \verb!}!;
% \textbf{nested} for languages with one kind of comment, which can be
% nested, e.g.\ Modula-2.
% The declaration of such comments is similar to comment lines.
% The character sequences are separated by one blank space, e.g.\ 
% \begin{verbatim}
%    \DeclareSingleComment /* */\relax
%    \DeclareDoubleComment (* *) { }\relax
%    \DeclareNestedComment (* *)\relax\end{verbatim}
% But hold on: When we input a listing, the characters must have the
% same category codes. So the examples won't work without changing
% them. See section \ref{ssSpecialCharacters}. If you don't want
% comments, let the second parameter of \cs{DeclareSingleComment}
% empty, i.e.\ type something like
% \begin{verbatim*}
%    \DeclareSingleComment stuff \relax\end{verbatim*}
%
% Note: Any language selecting command will reset keywords, comments
% and stringizer. You possibly need to redefine them, when you call
% such a command.
%
%
% \subsection{It's not all fine}
%
% Please be patient of my English.
%
% Not all languages have been tested fully, since I don't know all
% languages well. Hope I haven't forgotten any important feature of
% a language.
%
% I have considered to implement more languages, e.g.\ Matlab.
% But there are so many potential keywords and I don't want to decide,
% which words should be marked. Help me!
%
% You're not lucky about the listings package? You found errors?
% Damn and blast it or contact me:
% \begin{verbatim}
%    cheinz@wmpi04.math.uni-wuppertal.de\end{verbatim}
%
%
% \StopEventually{}
%
%
% \section{How the package works}
%
% What happens when a user calls \cs{inputlisting}? First we set up a
% bit (execute prelisting, open input file, do other initialization)
% and at the end we have to close the input file for example.
%
%
% \subsection{The main idea}
% The interesting part is the loop between: The source file is read,
% processed and typeset line by line. Before looking closer we have to
% deal with the alignment of columns, since this influences processing
% and typesetting. The problem: I don't like listings, which are
% printed with typewriter fonts. But only in these fonts all characters
% have the same width. So we have to handle different widths.
% The Pascal source lines
% \begin{verbatim}
%    if x=y then write('alignment')
%           else print('alignment');\end{verbatim}
% shouldn't come out as
% \begin{center}\hfill
% \begin{tabular}{l}
%	if\ x=y\ then\ write('alignment')\\
%	\ \ \ \ \ \ \ else\ print('alignment');
% \end{tabular}
% \hfill or \hfill
% \begin{tabular}{l@{\space}l@{\space}l}
%    \textbf{if} x=y&\textbf{then}&\textbf{write}('alignment')\\
%                   &\textbf{else}&print('alignment');
% \end{tabular}\hfill
% \end{center}
% only because blank spaces are not wide enough or because a bold
% letter has more width than a normal one.
%
% There is a simple trick to avoid things like that. We make boxes of
% the same width and put one character in each box:
% \begin{center}
%     \vbox{\def\makeboxes#1{\fbox{\hbox to 1em{\hss\vphantom{fy}#1%
%         \hss}}\ifx#1\relax\else\expandafter\makeboxes\fi}
%     \makeboxes if\ x=y\ then\ write\relax\space\ldots\\
%     \makeboxes \ \ \ \ \ \ \ else \ print\relax\space\ldots}
% \end{center}
% Going this way the alignment of columns can't be disturbed. But if
% the boxes are not wide enaugh, we get
% \begin{center}
%     \def\makeboxes#1{\hbox{\hbox to 0.15em{\hss\vphantom{fy}#1\hss}}%
%         \ifx#1\relax\else\expandafter\makeboxes\fi}
%     \begin{tabular}{l}
%     \makeboxes if\ x=y\ then\ write\relax\space\ldots
%     \end{tabular}
% \end{center}
% And choosing the width so that the widest character fits in, leads
% to
% \begin{center}
%     \def\makeboxes#1{\hbox to 0.7em{\hss\vphantom{fy}#1\hss}%
%         \ifx#1\relax\else\expandafter\makeboxes\fi}
%     \begin{tabular}{l}
%     \makeboxes if\ x=y\ then\ write\relax\space\ldots
%     \end{tabular}
% \end{center}
% Both are not acceptable. So there is more to do. Each input line
% will be cut up in logical units. Since we want to scan for keywords,
% this is no extra work. In the example the units are
% \begin{center}\begin{tabular}{ccccccc}
%     if, & x, & =, & y, & then, & write, & \ldots
% \end{tabular}\end{center}
% and the blank spaces between. We put each unit in a box, which width
% is multiplied by the number of characters we put in, of course. The
% result is
% \begin{center}
%     \def\makeboxes#1#2{\fbox{\hbox to #1em{\hss\vphantom{fy}#2\hss}%
%         }\ifx#2\relax\else\expandafter\makeboxes\fi}
%     \begin{tabular}{l}
%     \makeboxes2{i\hss f}1{\ }1{x}1{=}1{y}1{\ }4{t\hss h\hss e\hss n}%
%         1{\ }5{w\hss r\hss i\hss t\hss e}1\relax\space\ldots
%     \end{tabular}
% \end{center}
% Now we are ready to choose the base width of a box. Consider the
% 'write'. The 'w' needs more space than base width, but the 'i' needs
% less. This will compensate each other, because we put them in the
% same box. In general: Since wide characters use space actually
% reserved for thin characters, the base width need not to be the
% width of the widest character. This would be 1em (a \cs{quad}).
% But we use the empirical value 0.65em. It's a compromise between
% overlapping characters and the number of boxes exceeding not the
% textwidth, i.e.\ how many characters fit a line without getting an
% overfull \verb!\hbox!.
%
% 
% \subsection{Line processing}
% Let's discuss the line processing. The job is to classify comments,
% strings and other source code, where we search for keywords. We do
% that in several steps.
% \begin{itemize}
% \item First we pay attention on comments, which started in preceding
%	lines, e.g.\ 
%	\begin{verbatim}
%    comment } for i:=1 to maxint do ...\end{verbatim}
%	In that case we look for the end of comment and output the comment.
%	If there is other source code left, we run the line processing on
%	that code.
% \item If no comment is in work, we look for one and split the input
%	into comment and other source code. Since the other code comes
%	first, we give it to a routine, which cuts it into the units
%	described above (tokenizing). The output takes place there.
% \item Afterwards we have to output the comment. But when we look for
%	a comment, we don't take notice of other things. Consider
%	\begin{verbatim}
%    writeln('This is a string { and not a comment }');\end{verbatim}
%	We cut this line at the left brace into other code and comment.
%	After typesetting the other code we notice, that a string started,
%	but hasn't been finished. Our first classification was wrong.
%	We use the comment as new input and simply run the line processing
%	again to continue the string.
% \item If all strings are finished, we can output the comment, since
%	it's really a comment.
% \end{itemize}
% This is a sketch of line processing. For more detailed information
% see section \ref{ssLineProcessing}, where the implementation is
% described.
%
% One question about the third item is left: Why do we cut off a
% comment, even if we don't know that it is a comment? It's a matter
% of modularity and extension. Consider the alternative: The tokenize
% routine below (where we cut the classified input into the smallest
% units) would have to look for the start and end of comment.
% To support different languages we have to write either more than one
% tokenize routine or one, which handles comments of all languages.
% Adding another language means extending tokenizing or writing a new
% routine, which looks only for the particular comment. But finding a
% comment has nearly nothing to do with looking for delimiters (blank
% space, comma, plus, bracket, etc.). So we write exactly one tokenize
% macro and have several routines finding a comment to support different
% languages.
%
%
% \subsection{Tokenizing}
% The next step is breaking up the parts produced by line processing
% into the units mentioned above. We gather all characters, until
% reaching a nonletter. Then we output the collected characters using
% a routine, which selects the right style (comment, keyword, string).
% Afterwards we handle the nonletter:
%
% If it is a stringizer, we switch a string boolean to indicate whether
% we are in string mode or not. This boolean is also used by the line
% processing.
%
% If we found a tabulator, we typeset blank spaces to reach the next
% tabulator stop. The output routines are responsible for knowing the
% number of blanks we need.
%
%
% \subsection{Special characters}\label{SpecialCharacters}
% As you know some characters have a special meaning to \TeX, e.g.\ the
% subscript \verb!_! or the backslash \verb!\!. \TeX{} realizes this
% using so called category codes (catcodes). \TeX{} knows sixteen
% different ones:
% \begin{center}\begin{tabular}{rll}
%	 0 & escape delimiter (backslash)& \verb!\catcode`\\=0!\\
%	 1 & beginning of a group ($\{$)& \verb!\catcode`\{=1!\\
%	 2 & ending of a group ($\}$)	& \verb!\catcode`\}=2!\\
%	 3 & mathematics shift ($\$$)	& \verb!\catcode`\$=3!\\
%	 4 & tabulator ($\&$)		& \verb!\catcode`\&=4!\\
%	 5 & end of line (carriage return)& \verb!\catcode`\^^M=5!\\
%	 6 & macro parameter (\verb!#!) & \verb!\catcode`\#=6!\\
%	 7 & superscript (\verb!^!)	& \verb!\catcode`\^=7!\\
%	 8 & subscript (\verb!_!)	& \verb!\catcode`\_=8!\\
%	 9 & ignore			& \verb!\catcode`\^^@=9!\\
%	10 & blank space		& \verb!\catcode`\ =10!\\
%	11 & letter			& A..Z,a..z\\
%	12 & other			& \\
%	13 & active (e.g.\ \verb!~!)	& \\
%	14 & comment			& \verb!\catcode`\%=14!\\
%	15 & invalid characters		&
% \end{tabular}\end{center}
% When \TeX{} reads a character, it looks up the associated catcode and
% treats the character accordingly, e.g.\ an active character stands
% for a command without a leading backslash (like \verb!~! or the
% double quote in \verb!german.sty!).
%
% We can't change catcodes of characters, which \TeX{} has already
% read. But we are able to change them before. After
% \verb!\catcode`\A=10! an upper 'A' has the same effect as a blank
% space! Consider the \TeX-source
% \begin{verbatim}
%    \def\uppera{A} % saving upper 'A'; we can't use \upperA. Why?
%    \catcode`\A=10 % 'A' becomes blank space. That's the reason!
%    MayAbeAaAcuriousAexample. \upperaAnd it work's.\end{verbatim}
% The output is
% \begin{verbatim}
%    May be a curious example. And it work's.\end{verbatim}
% First we save the 'A'. Changing the catcode has no effect on the
% definition in the first line, since \TeX{} has read it before. All
% coming 'A' are blank spaces.
%
% We want to input and typeset characters 'as they are'. But the
% subscript or the macro parameter character are not printable. So it
% is necessary to change catcodes. We make these characters active.
% We also change catcodes of printable characters, e.g.\ a digit
% (normally other) will be treated as a letter, since indentifiers like
% \verb!x1!, \verb!y2! are legal. Then it is possible to gather all
% characters upto a nonletter to cut up a unit!
%
% We change catcodes for input and output. That's clear. But we also
% do it to define some commands. One example: In Pascal we have to look
% for \verb!{!. Let's say, we compare it with a left brace from a
% source file. This only works, if both have the same meaning.
% And when we declare the comment, \TeX{} must know the associated
% catcode, since it can't be changed later.
% Hence, we have to change it also at the time of defining the macros.
%
% There is at least one more thing to say: Catcodes aren't easy to
% work with.
%
%
% \section{Implementation}
%
% Before considering the implementation, here some conventions I used:
% \begin{itemize}
% \item The name of all public macros (the user commands) use lowercase
%	letters.
% \item The name of all private macros and variables use the prefix
%	\verb!lst@!.
% \item To distinguish procedure-like macros from macros holding data,
%	the name of procedure macros use uppercase letters with each
%	beginning word, e.g.\ \verb!\lst@ProcessLine!.
% \end{itemize}
%
%
% \subsection{Options}\label{ssOptions}
% First we declare the options, which are executed and processed at
% the very end of this file. They call the language commands.
%    \begin{macrocode}
%<*package>
\DeclareOption{blank}  {\blanklisting}
\DeclareOption{c}      {\clisting}
\DeclareOption{cpp}    {\cpplisting}
\DeclareOption{eiffel} {\eiffellisting}
\DeclareOption{fortran}{\fortranlisting}
\DeclareOption{java}   {\javalisting}
\DeclareOption{modula} {\modulalisting}
\DeclareOption{pascal} {\pascallisting}
\DeclareOption{pxsc}   {\pxsclisting}
\DeclareOption{tp}     {\tplisting}
%    \end{macrocode}
%
% The language commands call \verb!\lst@Listing! to load the language
% driver file and to select the language.
%    \begin{macrocode}
\newcommand\blanklisting  {\lst@Listing{blank}}
\newcommand\clisting      {\lst@Listing{c}}
\newcommand\cpplisting    {\lst@Listing{cpp}}
\newcommand\eiffellisting {\lst@Listing{eiffel}}
\newcommand\fortranlisting{\lst@Listing{fortran}}
\newcommand\javalisting   {\lst@Listing{java}}
\newcommand\modulalisting {\lst@Listing{modula}}
\newcommand\pascallisting {\lst@Listing{pascal}}
\newcommand\pxsclisting   {\lst@Listing{pxsc}}
\newcommand\tplisting     {\lst@Listing{tp}}
%    \end{macrocode}
%
% \begin{macro}{\lst@Listing}
% This command loads the specified driver file and selects the language.
% We give an error message, if the driver file doesn't support the
% necessary macro.
%    \begin{macrocode}
\newcommand\lst@Listing[1]{%
    \@ifundefined{lst@#1}{\input{lst#1.sty}}{}%
    \@ifundefined{lst@#1}{%
        \PackageError{Listings}{Driver file for `#1' corrupt}{%
        The driver file doesn't define the macro \string\lst@#1.}}%
    {\csname lst@#1\endcsname \def\lst@curr{#1}}}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Registers and variables}\label{ssRegisters}
% We will need some variables.
%
% \begin{macro}{\lst@inputfile}\begin{macro}{\if@lst@endinput}
% \begin{macro}{\iflisting}
% The logical input file is \verb!\lst@inputfile!. The output of the
% file terminates, if and only if the boolean \verb!\if@lst@endinput!
% is true. \verb!\iflisting! is described in the user's guide.
%    \begin{macrocode}
\newread\lst@inputfile  \newif\if@lst@endinput  \newif\iflisting
%    \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lst@last@line}\begin{macro}{\lst@current@line}
% The user specified last line and the current input line are kept
% in two counters:
%    \begin{macrocode}
\newcount\lst@last@line  \newcount\lst@current@line
%    \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\if@lst@comment}\begin{macro}{\if@lst@string}
% \begin{macro}{\lst@comment@depth}
% Comments (not whole comment lines) and strings are indicated by
% following booleans. The current comment depth uses a counter.
%    \begin{macrocode}
\newcount\lst@comment@depth
\newif\if@lst@comment  \newif\if@lst@string
%    \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lst@width}\begin{macro}{\lst@length}
% The dimension \verb!\lst@width! holds the width of a single character
% box and is set to 0.65em, when we output a listing. The counter
% \verb!\lst@length! holds the length of the current character string
% we want to output.
%    \begin{macrocode}
\newdimen\lst@width  \newcount\lst@length
%    \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@tab@length}\begin{macro}{\lst@pos}
% The first counter saves the parameter of the \cs{tablength} command.
% \verb!\lst@pos! holds the current column number to handle tabulators.
%    \begin{macrocode}
\newcount\lst@tab@length  \newcount\lst@pos
%    \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@line} \begin{macro}{\lst@comment}
% \begin{macro}{\lst@commentline}
% Some variables need no allocation here, since they are macros, e.g.\ 
% most user commands save their parameter within a macro. The most
% important 'data' macros are \verb!\lst@line!, \verb!\lst@comment!
% and \verb!\lst@commentline!. They hold the current line, comment and
% comment line for line processing.
% \end{macro}\end{macro}\end{macro}
%
%
% \subsection{Comments}\label{ssComments}
%
% First we discuss comment lines (CL). Let's say, we have a C++ source
% line with a comment, which is separated by '//'. To cut the line into
% code and comment we use a macro like this:
% \DescribeMacro\lst@CutCL
% \begin{verbatim}
%    \def\lst@CutCL#1//#2\relax{%
%        \def\lst@line{#1}%
%        \def\lst@commentline{//#2}%
%    }\end{verbatim}
% The parameter definition ensures, that the first parameter holds the
% code and our second paramater the comment upto a \cs{relax}, which
% will terminate the input. We redefine the input and comment line,
% where we must add the separator '//' again. That's easy.
% \DescribeMacro\lst@CommentLine
% But if we call this macro using a line without any '//', \TeX{}
% detects a syntax error, since the line doesn't meet the definition.
% Hence, to look for a comment line we can't use the cut macro, but
% this:
% \begin{verbatim}
%    \def\lst@CommentLine{%
%        \expandafter\lst@TestCL\lst@line//\relax %
%    }\end{verbatim}
% Additional '//' and '\cs{relax}' hold up the syntax of the cut macro.
% That's the point. We use an \cs{expandafter}, because we need the
% \emph{content} of \verb!\lst@line! and not the token itself as
% parameter. So the test macro is called (or expanded) after the
% content is written behind.
% \DescribeMacro\lst@TestCL
%
% Why we don't use the cut macro here? Our additional '//' would be
% added to the comment! Therefore:
% \begin{verbatim}
%    \def\lst@TestCL#1//#2\relax{%
%        \def\test{##2}%
%        \ifx\test\empty %
%            \let\lst@commentline=\empty %
%        \else %
%            \expandafter\lst@CutCL\lst@line\relax %
%        \fi %
%    }\end{verbatim}
% If you compare the definition of \verb!\lst@TestCL! here and the
% call above, you will see: The second parameter is empty, if and only
% if there is no comment (no double slash). So we are able to call
% the cut macro without additional '//', if we've found a comment.
%
% \begin{macro}{\DeclareCommentLine}
% \begin{macro}{\lst@CommentLine}
% \begin{macro}{\lst@TestCL}\begin{macro}{\lst@CutCL}
% Now comes the real implementation. It's different from the C++
% example, but it only seems to. The one and only parameter of
% \cs{DeclareCommentLine} ist the comment line separator.
% First we test, if comment lines are desired. If not, we let the main
% macro be empty. Otherwise we define three macros similar to the
% example. But: To distinguish their parameters from the comment line
% separator $\#1$, we have to double the '$\#$': The $n$th parameter
% of a macro within a macro is $\#\#n$. If you know this, following
% is clear: It's the same as the simplified example.
%    \begin{macrocode}
\def\DeclareCommentLine#1\relax{\def\test{#1}%
  \ifx\test\empty \let\lst@CommentLine=\empty %
  \else
      \gdef\lst@CommentLine{\expandafter\lst@TestCL\lst@line#1\relax}%
      \long\gdef\lst@TestCL##1#1##2\relax{%
          \def\test{##2}%
          \ifx\test\empty \let\lst@commentline=\empty %
          \else \expandafter\lst@CutCL\lst@line\relax %
          \fi}%
      \gdef\lst@CutCL##1#1##2\relax{%
          \def\lst@line{##1}\def\lst@commentline{#1##2}}%
  \fi}
%    \end{macrocode}
% \end{macro}\end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\DeclareSingleComment}
% \begin{macro}{\lst@SOC}\begin{macro}{\lst@EOC}
% For single comments we use the same cut mechanism as above, except
% that we use it for the start of comment (SOC) and for the end of
% comment (EOC): We define six macros here. Additional the comment
% boolean is switch by the cut macros. The two parameters of
% \cs{DeclareSingleComment} are the character sequences for the
% beginning and ending of a single comment, of course.
%    \begin{macrocode}
\def\DeclareSingleComment#1 #2\relax{\def\test{#2}%
  \ifx\test\empty %
      \let\lst@SOC=\empty \let\lst@EOC=\empty %
  \else %
      \gdef\lst@SOC{\expandafter\lst@TestSOC\lst@line#1\relax}%
      \long\gdef\lst@TestSOC##1#1##2\relax{%
          \def\test{##2}%
          \ifx\test\empty\else %
              \expandafter\lst@CutSOC\lst@line\relax %
          \fi}%
      \gdef\lst@CutSOC##1#1##2\relax{\@lst@commenttrue %
          \def\lst@line{##1}\def\lst@comment{#1##2}}%
      \gdef\lst@EOC{\expandafter\lst@TestEOC\lst@line#2\relax}%
%    \end{macrocode}
%    \begin{macrocode}
      \long\gdef\lst@TestEOC##1#2##2\relax{%
          \def\test{##2}%
          \ifx\test\empty %
%    \end{macrocode}
% Here we are in the situation, that we look for the end of comment but
% haven't found one. Since we are in comment mode, the whole line is
% the comment and the line gets empty.
%    \begin{macrocode}
              \let\lst@comment=\lst@line \let\lst@line=\empty %
          \else %
              \expandafter\lst@CutEOC\lst@line\relax %
          \fi}%
      \gdef\lst@CutEOC##1#2##2\relax{\@lst@commentfalse %
          \def\lst@line{##2}\def\lst@comment{##1#2}}%
  \fi}
%    \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\DeclareDoubleComment}
% First steps of declaring a double comment are easy: We declare a
% single comment and define macros for a second single comment with
% slightly different names (an additional \verb!@! after \verb!SOC!
% and \verb!EOC!).
%    \begin{macrocode}
\def\DeclareDoubleComment#1 #2 #3 #4\relax{%
  \DeclareSingleComment#1 #2\relax %
  \global\let\lst@SavedEOC=\lst@EOC %
  \long\gdef\lst@TestSOC@##1#3##2\relax{%
      \def\test{##2}%
      \ifx\test\empty\else %
          \expandafter\lst@CutSOC@\lst@line\relax %
      \fi}%
  \gdef\lst@CutSOC@##1#3##2\relax{\@lst@commenttrue %
      \def\lst@line{##1}\def\lst@comment{#3##2}}%
  \gdef\lst@EOC@{\expandafter\lst@TestEOC@\lst@line#4\relax}%
  \long\gdef\lst@TestEOC@##1#4##2\relax{%
      \def\test{##2}%
      \ifx\test\empty %
          \let\lst@comment=\lst@line \let\lst@line=\empty %
      \else %
          \expandafter\lst@CutEOC@\lst@line\relax %
      \fi}%
  \gdef\lst@CutEOC@##1#4##2\relax{\@lst@commentfalse %
      \def\lst@line{##2}\def\lst@comment{##1#4}}%
%    \end{macrocode}
% Now we compose the two single comments by redefining a test macro.
% The job is to coincide start and end of comment: We have to look,
% whether the first, the second or none comment starts, and must
% select the right macro to find the corresponding end of comment.
%    \begin{macrocode}
  \long\gdef\lst@TestSOC##1#1##2\relax{%
%    \end{macrocode}
% Now $\#\#1$ holds the code of the line and $\#\#2$ (possibly) the
% comment. But we have to look whether the other comment type starts
% before this here or not. So we call the test macro of the other
% comment first. If we've found one, we let \verb!\lst@EOC! be the
% macro, which looks for the end of that comment.
%    \begin{macrocode}
      \lst@TestSOC@##1#3\relax %
      \if@lst@comment \let\lst@EOC=\lst@EOC@ %
%    \end{macrocode}
% Otherwise we do the test for this comment. If there is a comment,
% we cut up the line and let \verb!\lst@EOC! be the macro, which
% looks for the end of this comment.
%    \begin{macrocode}
      \else \def\test{##2}%
          \ifx\test\empty \else %
              \expandafter\lst@CutSOC\lst@line\relax %
              \let\lst@EOC=\lst@SavedEOC %
          \fi %
      \fi}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\DeclareNestedComment}
% For nested comments we do it the same way: We declare a single
% comment and adjust some macros. Testing for an end of comment is
% nearly the same as for single comments.
%    \begin{macrocode}
\def\DeclareNestedComment#1 #2\relax{%
  \DeclareSingleComment#1 #2\relax %
  \long\gdef\lst@TestEOC##1#2##2\relax{%
%    \end{macrocode}
% The only difference is, that we have to count how many (new) comments
% start in the comment. And this is done here, the rest is the same as
% above.
%    \begin{macrocode}
      \lst@CountSOC##1#1\relax %
      \def\test{##2}%
      \ifx\test\empty %
          \let\lst@comment=\lst@line \let\lst@line=\empty %
      \else %
          \expandafter\lst@CutEOC\lst@line\relax %
      \fi}%
%    \end{macrocode}
% An end of comment lets the comment depth decrease. If we reach 0,
% we set the comment boolean false. That's not new, since this happens
% always with not nested comments.
%    \begin{macrocode}
  \gdef\lst@CutEOC##1#2##2\relax{%
      \advance\lst@comment@depth by -1\relax %
      \ifnum 0=\lst@comment@depth \@lst@commentfalse\fi %
      \def\lst@line{##2}\def\lst@comment{##1#2}}%
%    \end{macrocode}
% Now we have to do something for increasing the comment depth. We
% count how many new comments start within a comment. To move through
% a comment we use the same separation mechanism as all the time. The
% second parameter is empty, if and only if there is no (more) start
% of comment. While it is not empty we increase the comment depth and
% call this macro again with the current rest of the comment.
%    \begin{macrocode}
  \long\gdef\lst@CountSOC##1#1##2\relax{%
      \def\test{##2}\ifx\test\empty\else %
          \advance\lst@comment@depth by 1%
          \def\@tempa{\lst@CountSOC##2\relax}%
%    \end{macrocode}
% Note: \verb!\@tempa! is executed after the closing \verb!\fi! to call
% the macro again.
%    \begin{macrocode}
          \expandafter\@tempa %
      \fi}}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Keywords}\label{ssKeywords}
%
% \begin{macro}{\lst@CaseSensitiveKeywords}
% We have to decide whether a given character sequence is a reserved
% word or not. Doing this test is very familiar with the cut mechanism
% for comments. To test, if \verb!key! is a keyword, we define a macro
% \begin{verbatim}
%    \def\test#1,key,#2\relax{...}\end{verbatim}
% Afterwards we call the macro with the parameters
% \begin{center}\begin{tabular}{l@{}l}
%    all current keywords&\verb!,key,\relax!
% \end{tabular}\end{center}
% When \TeX{} passes the arguments, the second parameter is empty,
% if and only if \verb!key! is not a current keyword. So we are able to
% decide whether to make a normal box, or a box with keywordstyle.
%    \begin{macrocode}
\def\lst@CaseSensitiveKeywords#1\relax{%
%    \end{macrocode}
% \cs{relax} terminates the character sequence we want to test. Now we
% define the test macro. It overwrites itself, but this happens after
% execution.
%    \begin{macrocode}
    \def\test##1,#1,##2\relax{\def\test{##2}%
        \ifx\test\empty \lst@MakeBox{}%
        \else \lst@MakeBox{\lst@keywordstyle}%
        \fi}%
%    \end{macrocode}
% We only need to call the macro defined right before.
% \verb!,#1,\relax! holds up the syntax of \cs{test}.
%    \begin{macrocode}
    \expandafter\test\lst@keywords,#1,\relax}%
%    \end{macrocode}
% Since \TeX{} always passes two arguments to the test macro, \TeX{}
% splits the \emph{whole} 'input' \verb!\lst@keywords,#1,\relax! into
% two parts. So there is no need to sort the keywords by probability.
% \end{macro}
%
% \begin{macro}{\lst@NonCaseSensitiveKeywords}
% Now we implement the test for keywords, which are not case sensitive.
% We use two uppercase to normalize the test string and the keywords.
% For the keywords we need some expandafters, so that the keywords are
% expanded before making the characters uppercase.
%    \begin{macrocode}
\def\lst@NonCaseSensitiveKeywords#1\relax{%
    \uppercase{\def\test##1,#1,##2\relax{\def\test{##2}%
        \ifx\test\empty \lst@MakeBox{}%
        \else \lst@MakeBox{\lst@keywordstyle}%
        \fi}}%
    \expandafter\uppercase\expandafter{%
        \expandafter\test\lst@keywords,#1,\relax}}%
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Commands}\label{ssCommands}
% \begin{macro}{\prelisting}\begin{macro}{\postlisting}
% \begin{macro}{\keywordstyle}\begin{macro}{\commentstyle}
% \begin{macro}{\stringstyle}\begin{macro}{\keywords}
% \begin{macro}{\morekeywords}\begin{macro}{\stringizer}
% The following user commands save the parameter in private macros.
%    \begin{macrocode}
\newcommand\prelisting[1]{\def\lst@prelisting{#1}}
\newcommand\postlisting[1]{\def\lst@postlisting{#1}}
\newcommand\keywordstyle[1]{\def\lst@keywordstyle{#1}}
\newcommand\commentstyle[1]{\def\lst@commentstyle{#1}}
\newcommand\stringstyle[1]{\def\lst@stringstyle{#1}}
\newcommand\keywords[1]{\def\lst@keywords{#1}}
\newcommand\morekeywords[1]{\edef\lst@keywords{\lst@keywords,#1}}
\newcommand\stringizer[1]{\def\lst@stringizer{#1}}
%    \end{macrocode}
% \end{macro}\end{macro}\end{macro}\end{macro}
% \end{macro}\end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\blankstringtrue}\begin{macro}{\blankstringfalse}
% \begin{macro}{\sensitivetrue}\begin{macro}{\sensitivefalse}
% The user 'switches' assign the right macros.
%    \begin{macrocode}
\newcommand\blankstringtrue{%
    \let\lst@MakeStringBox=\lst@MakeBox}
\newcommand\blankstringfalse{%
    \let\lst@MakeStringBox=\lst@MakeSpecialStringBox}
\newcommand\sensitivetrue{%
    \let\lst@KeywordOrNot=\lst@CaseSensitiveKeywords}
\newcommand\sensitivefalse{%
    \let\lst@KeywordOrNot=\lst@NonCaseSensitiveKeywords}
%    \end{macrocode}
% \end{macro}\end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\tablength}
% \cs{tablength} first look, if the argument is legal.
% If not, an error message is given.
%    \begin{macrocode}
\newcommand\tablength[1]{\ifnum#1>0\lst@tab@length=#1\relax \else %
    \PackageError{Listings}{Strict positive integer expected}{%
    You can't use `#1' as tablength.^^J I'll forget it and proceed.}\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\normallisting}
% The default style is set using commands from above:
%    \begin{macrocode}
\newcommand\normallisting{%
    \keywordstyle{\bfseries}\commentstyle{\itshape}\stringstyle{}%
    \prelisting{}\postlisting{}\blankstringfalse}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\inputlisting}
% Now we define the main command. The first parameter is optional and
% set to $[1,999999]$, if none is given. The second parameter is the
% filename. If the file doesn't exist, we give an error message.
% Otherwise we skip the lines upto the first printing line and output
% the listing, but only, if listings are desired. The inner loop
% terminates, if the end of file or the specified last line is reached.
%    \begin{macrocode}
\newcommand\inputlisting[2][1,999999]{%
    \batchmode \openin\lst@inputfile#2 \errorstopmode %
    \ifeof\lst@inputfile %
        \PackageError{Listings}{File `#2' not found}{%
        You must tell me the right name or I can't do the job.}%
    \else %
        \message{(#2}%
        \iflisting %
            \lst@SetRange[#1]\lst@current@line=1 %
            \lst@SkipUptoFirst \@lst@endinputfalse %
            \lst@begin %
            \loop %
                \read\lst@inputfile to\lst@line %
                \advance\lst@current@line by 1%
                \lst@AllLineProcessing %
                \ifeof\lst@inputfile \@lst@endinputtrue \fi %
                \ifnum\lst@last@line<\lst@current@line %
                    \@lst@endinputtrue %
                \fi %
                \if@lst@endinput\else %
            \repeat %
            \vspace*{-\baselineskip}%
            \lst@end %
%    \end{macrocode}
% If listings aren't desired, we typeset a message.
%    \begin{macrocode}
        \else %
            \begin{center}%
            --- Listing of #2 has been skipped. ---
            \end{center}%
        \fi %
        \message{)}%
%    \end{macrocode}
% The corresponding \cs{fi} from 'if file exists' and close the input
% file.
%    \begin{macrocode}
    \fi \closein\lst@inputfile}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\listing}
% Now we define the environment for typesetting listings. The command
% for beginning the environment is easy. To read the \TeX-file line
% by line we have to make the end of line character \verb!^^M! active.
% But this only happens, if listings are allowed.
% Ending the environment is very easy.
%    \begin{macrocode}
\def\listing{%
    \iflisting
        \lst@begin \catcode`\^^M=\active \vspace*{-\baselineskip}%
        \expandafter\lst@env@ReadAndProcess %
    \else %
        \begin{center}%
        --- Listing has been skipped. ---
        \end{center}%
    \fi}
\def\endlisting{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@env@ReadAndProcesss}
% We will use a mechanism used for the new implementation of \LaTeX's
% \verb!verbatim! environments. I don't explain it here. It is
% described in section 3.4 of \cite{verbatim}.
%    \begin{macrocode}
\begingroup
\catcode`\!=\active \catcode`\[=\active \catcode`\]=\active
\lccode`\!=`\\ \lccode`\[=`\{ \lccode`\]=`\}
\catcode`\~=\active \lccode`\~=`\^^M
\lowercase{
%    \end{macrocode}
% The effect of lowercase is that all \verb+!+, \verb![!, \verb!]!
% and \verb!~! of the argument are converted to \verb!\!, \verb!{!,
% \verb!}! and \verb!^^M!.
%
% The macro \verb!\lst@env@ReadAndProcess! gets the input upto the next
% end of line character. We append \verb!\end{listing}\relax!
% to hold up the syntax of \verb!\lst@env@Process!.
%    \begin{macrocode}
\gdef\lst@env@ReadAndProcess#1~{\lst@env@Process#1!end[listing]\relax}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@env@Processs}
% The second parameter of this macro is empty, if and only if the end
% of the environment is not reached. If the listing goes on, we define
% the current line, do the line processing and define the next macro.
% If the listing is over, we define right macro to be the next.
%    \begin{macrocode}
\gdef\lst@env@Process#1!end[listing]#2\relax{%
    \def\test{#2}%
	\ifx\test\empty %
        \def\lst@line{#1~}%
        \lst@AllLineProcessing %
        \let\next\lst@env@ReadAndProcess %
    \else %
        \def\next{\lst@end\end{listing}}%
    \fi\next}
}\endgroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@begin} \begin{macro}{\lst@end}
% Let's look what's to do to begin and end a listing, respectively.
% We insert a small skip, the user defined \verb!\lst@prelisting!
% and \verb!\lst@postlisting! and initialize some variables.
% Of course, we use a new group level, so that outer blocks are not
% affected by the changes made here.
%    \begin{macrocode}
\def\lst@begin{%
    \smallbreak\bgroup\lst@prelisting %
    \@lst@stringfalse \lst@width=0.65em \lst@comment@depth=0 %
    \let\lst@comment=\empty \let\lst@commentline=\empty %
    \def\lst@test{fortran}\ifx\lst@curr\lst@test \lst@width=0.8em\fi
    \lst@ChangeCatcodes}
\def\lst@end{\lst@postlisting\egroup\smallbreak\ignorespaces}
%    \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@SetRange}\begin{macro}{\lst@SkipUptoFirst}
% Here are two simple macros we used some time before.
% The counter \verb!\@tempcnta! is temporary.
%    \begin{macrocode}
\def\lst@SetRange[#1,#2]{\@tempcnta=#1\relax \lst@last@line=#2\relax}
\def\lst@SkipUptoFirst{%
    \@whilenum \@tempcnta<\lst@current@line \do %
        {\read\lst@inputfile to\lst@line %
         \advance\lst@current@line by 1}}
%    \end{macrocode}
% \end{macro}\end{macro}
%
%
% \subsection{Line processing}\label{ssLineProcessing}
%
% \begin{macro}{\lst@AllLineProcessing}
% Here comes the single line processing. First we collect the line
% processing in one macro: Some initialization, pre-processing and
% the processing.
%    \begin{macrocode}
\def\lst@AllLineProcessing{%
    \let\lst@text=\empty \lst@length=0 \global\lst@pos=0 %
    \par \noindent \lst@PreProcessLine \lst@ProcessLine}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@PreProcessLineDefault}
% Before considering the main macro we define the default for
% \verb!\lst@PreProcessLine!. It gives a warning, if a string exceeds
% a line.
%    \begin{macrocode}
\def\lst@PreProcessLineDefault{%
    \if@lst@string %
        \PackageWarning{Listings}{string constant exceeds line}%
        \@lst@stringfalse %
    \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@ProcessLine}
% Now the main macro for line processing. There is no parameter,
% because the data is given by \verb!\lst@line!. We construct a loop
% by defining the macro \cs{next} to call this macro again. But this
% definition might changes soon to terminate line processing.
%    \begin{macrocode}
\def\lst@ProcessLine{\def\next{\lst@ProcessLine}%
%    \end{macrocode}
% Since a comment might exceeds a line, we have to handle this case
% first. We try to find the end of comment, which saves the comment
% in \verb!\lst@comment! and might changes the boolean
% \verb!\if@lst@comment!.
%    \begin{macrocode}
    \if@lst@comment \lst@EOC %
%    \end{macrocode}
% To output the comment we use a little trick (concerning the naming
% of a macro). The tokenize macro below not only cuts up the input for
% scanning keywords. In comment mode it will cut the input in the same
% way, but always uses commentstyle for the output. Therefore we
% locally switch to comment mode and call the macro.
%    \begin{macrocode}
        {\@lst@commenttrue \expandafter\lst@Tokenize\lst@comment\relax}%
%    \end{macrocode}
% We empty the comment just output. If the comment goes on, i.e.\ the
% comment was the whole line, line processing is over, i.e.\ there is
% nothing to do next: We redefine the macro \cs{next}.
%    \begin{macrocode}
        \let\lst@comment=\empty\if@lst@comment \def\next{}\fi %
    \else %
%    \end{macrocode}
% If no comment is in progress, the macro tries to find one and cuts
% off a comment line, if possible (or a part of the line as a comment
% line).
%    \begin{macrocode}
        \lst@SOC \lst@CommentLine %
%    \end{macrocode}
% Now \verb!\lst@line! has been cut to the noncomment rest.
% We have to find the keywords. \cs{relax} is used as a brake:
% It marks the end and will terminate tokenizing.
%    \begin{macrocode}
        {\@lst@commentfalse\expandafter\lst@Tokenize\lst@line\relax}%
%    \end{macrocode}
% If a string has begun in \verb!\lst@Tokenize!, but not finished,
% the potential comment above belongs to the string. What's to do? The
% input line gets the comment and the next character is typeset. Then
% we call this macro without being in danger classifing the comment as
% a comment again, because the first character is missing now. But
% hold on: The comment might be empty and so the input line. In that
% case we have nothing to do next and \verb!\lst@PreProcessLine! might
% gives a warning to the user.
%    \begin{macrocode}
        \if@lst@string %
            \@lst@commentfalse %
            \ifx\lst@commentline\empty\else \@lst@commenttrue \fi %
            \ifx\lst@comment\empty\else \@lst@commenttrue \fi %
            \if@lst@comment %
                \@lst@commentfalse %
                \expandafter\expandafter\expandafter\lst@TypesetChar %
                    \expandafter\lst@commentline\lst@comment\relax %
                \let\lst@comment=\empty \let\lst@commentline=\empty %
            \else %
                \def\next{}%
            \fi %
        \else %
%    \end{macrocode}
% If no string is in work, it's all fine. We output the comment line,
% if present. In that case there is no other comment.
%    \begin{macrocode}
            \ifx\lst@commentline\empty \else %
                \@lst@commenttrue %
                \expandafter\expandafter\expandafter\lst@Tokenize %
                    \expandafter\lst@commentline\lst@comment\relax %
                \let\lst@comment=\empty \let\lst@commentline=\empty %
                \@lst@commentfalse %
            \fi %
%    \end{macrocode}
% For comments this macro calls itself to find the end of comment.
% As this is the default, we only have to assign the comment to
% \verb!\lst@line! --- the implizit parameter of this macro.
% If there is no comment, we redefine \cs{next}.
%    \begin{macrocode}
            \if@lst@comment %
                \let\lst@line=\lst@comment %
            \else \def\next{}%
            \fi %
%    \end{macrocode}
% We have to close some ifs and do the next thing.
%    \begin{macrocode}
        \fi %
    \fi\next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@TypesetChar}
% The following macro has been used in the last macro. It typesets the
% next character and removes it from the input line.
%    \begin{macrocode}
\def\lst@TypesetChar#1#2\relax{\def\lst@line{#2}\lst@CharOutput#1}
%    \end{macrocode}
% \end{macro}
% The line processing is complete. Now we will try to scan keywords.
%
%
% \subsection{Tokenizing}\label{ssTokenizing}
% \begin{macro}{\lst@Tokenize}
% The tokenize macro gets code upto \cs{relax} and scans for keywords
% and strings. In fact it only cuts up potential keywords, which are
% tested right before their output. Most time we will call the tokenize
% macro again, since \cs{relax} is only read at the end. So we define
% the next operation first:
%    \begin{macrocode}
\long\def\lst@Tokenize#1{%
    \def\lst@next{\lst@Tokenize}%
%    \end{macrocode}
% An incoming letter is gathered.
%    \begin{macrocode}
    \ifcat #1a%
        \edef\lst@text{\lst@text#1}\advance\lst@length by 1 %
%    \end{macrocode}
% If we found a tabulator, we output the preceding text and go to the
% next tabulator stop.
%    \begin{macrocode}
    \else \ifcat #1&%
        \lst@Output \lst@GotoNextTabStop %
%    \end{macrocode}
% If we found other nonletter, we also output the preceding text.
% The keyword test take place there.
%    \begin{macrocode}
    \else %
        \lst@Output %
%    \end{macrocode}
% Getting to the terminator \cs{relax} ends tokenizing by defining
% next operation empty. Otherwise we look for the character, which
% begins and ends a string, but only if we don't process a comment.
%    \begin{macrocode}
        \ifx#1\relax \def\lst@next{}%
        \else \if@lst@comment \lst@CharOutput#1%
        \else \lst@TestStringizer#1%
        \fi \fi %
    \fi \fi \lst@next}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@TestStringizer}
% Here we do the stringizer tests. If a string already started, we
% output the current character, look for the closing stringizer and
% switch the string boolean, if we found it.
%    \begin{macrocode}
\long\def\lst@TestStringizer#1{\def\test{#1}%
    \if@lst@string %
        \lst@CharOutput#1%
        \ifx \test\lst@closing@stringizer \global\@lst@stringfalse\fi %
%    \end{macrocode}
% If we are not in string mode, we compare the current character with
% all given stringizers, and output the character afterwards.
% \cs{relax} is a terminator.
%    \begin{macrocode}
    \else %
        \expandafter\lst@DoStringizerTest\lst@stringizer\relax %
        \lst@CharOutput#1%
    \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@DoStringizerTest}
% Now we consider a stringizer test. Reaching \cs{relax} results in
% doing nothing and so terminating the tests.
%    \begin{macrocode}
\def\lst@DoStringizerTest#1{%
    \ifx#1\relax \else %
%    \end{macrocode}
% Otherwise we compare the current character and the current stringizer.
% If they are equal, we switch the string boolean and save the
% stringizer as closing stringizer.
%    \begin{macrocode}
        \expandafter\if\test#1%
            \global\@lst@stringtrue %
            \gdef\lst@closing@stringizer{#1}%
        \fi %
%    \end{macrocode}
% At the end we call this macro again. The macro terminates reaching
% the \cs{relax}!
%    \begin{macrocode}
        \expandafter\lst@DoStringizerTest %
    \fi}%
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Output}\label{ssOutput}
% \begin{macro}{\lst@Output}
% It's time to do text output. First we look, if there is anything to
% output.
%    \begin{macrocode}
\def\lst@Output{%
    \ifx\lst@text\empty\else %
%    \end{macrocode}
% Then we decide, whether to make a stringbox (using stringstyle) or
% a box for a comment (using commentstyle as explicit parameter).
% We distinguish a stringbox and a normal box with a given style,
% since this speeds up a bit. In strings we print \stringblank{}
% instead of a blank space. But this needs an additional if and more
% time.
%    \begin{macrocode}
        \if@lst@string \lst@MakeStringBox \else %
        \if@lst@comment\lst@MakeBox{\lst@commentstyle}\else %
%    \end{macrocode}
% If we output neither a string nor a comment, we look for a keyword.
% The output takes place in the macro \verb!\lst@KeywordsOrNot!
% (see section \ref{sLanguageDriverFiles}). \cs{relax} terminates the
% text parameter.
%    \begin{macrocode}
        \expandafter\lst@KeywordOrNot\lst@text\relax %
        \fi \fi %
%    \end{macrocode}
% Finally we hold up the current column, empty the text and close the
% starting 'if text not empty'.
%    \begin{macrocode}
        \global\advance\lst@pos by -\lst@length %
        \let\lst@text=\empty \lst@length=0 %
    \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@MakeBox}
% Consider the different boxes now. A box must take \verb!\lst@length!
% characters: the width is \verb!\lst@length!$\cdot$\verb!\lst@width!.
% The macro parameter possibly selects another style. We insert dynamic
% space at the beginning and at the ending to center the text and we
% fill the box. \cs{relax} is a brake.
%    \begin{macrocode}
\def\lst@MakeBox#1{%
    \hbox to \lst@length\lst@width{#1\hss %
        \expandafter\lst@FillBox\lst@text\relax \hss}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@FillBox}
% Filling up a box is easy. If we found the end of the text, we do
% nothing. Otherwise we output the character and insert dynamic space.
% Since the underbar is not a printable character in \TeX{}, we have
% to treat it special. By the way: We make the underbar having the
% letter catcode here; we don't want subscripts. After all this is
% done, we call the fillbox macro again.
% Note: The macro is called after the closing \cs{fi}!
%    \begin{macrocode}
\begingroup
\catcode`\_=11
\gdef\lst@FillBox#1{%
    \ifx\relax#1\else %
        \ifx#1_\lst@underbar \else #1\fi \hss %
        \expandafter\lst@FillBox %
    \fi}
\endgroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@MakeSpecialStringBox}
% A stringbox is nearly the same: The style parameter is replaced by
% stringstyle and we must fill a stringbox.
%    \begin{macrocode}
\def\lst@MakeSpecialStringBox{%
    \hbox to \lst@length\lst@width{\lst@stringstyle\hss %
        \expandafter\lst@FillStringBox\lst@text\relax \hss}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@FillStringBox}
% Filling the stringbox is more difficult. Again the subscript
% character becomes a letter. \verb!\lst@active@blank! is equal to a
% blank space, which comes from the source file. So we can use it for
% equality test to output a blank space as \stringblank.
%    \begin{macrocode}
\begingroup
\catcode`\_=11
\long\gdef\lst@FillStringBox#1{%
    \ifx\relax#1\else %
        \ifx#1_\lst@underbar \else %
        \ifx#1\lst@active@blank \lst@string@blank \else #1%
        \fi \fi \hss%
    \expandafter\lst@FillStringBox%
    \fi}%
\endgroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@CharOutput}
% We define one more macro to save time. It outputs a single character.
% The implementation should be clear.
%    \begin{macrocode}
\long\def\lst@CharOutput#1{\global\advance\lst@pos by -1%
    \hbox to \lst@width{\hss %
        \if@lst@string \lst@stringstyle\lst@FillStringBox#1\relax %
        \else \if@lst@comment \lst@commentstyle#1\hss %
        \else #1\hss %
        \fi \fi}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@GotoNextTabStop}
% At the end of this section we consider tabulators. As seen, each
% typeset character decrements the counter \verb!\lst@pos!. To go to
% the next tabulator stop, we must first determine how many blanks are
% needed. We simply add \verb!\lst@tab@length! until \verb!\lst@pos!
% is strict positive.
%    \begin{macrocode}
\def\lst@GotoNextTabStop{%
    \@whilenum \lst@pos<1 \do %
        {\global\advance\lst@pos by \lst@tab@length}%
%    \end{macrocode}
% Now we output \verb!\lst@pos! blank spaces and we are done.
% Note: \verb!\lst@pos! is decremented in \verb!\lst@CharOutput!.
%    \begin{macrocode}
    \@whilenum \lst@pos>0 \do %
        {\lst@CharOutput\lst@active@blank}}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Special characters}\label{ssSpecialCharacters}
% \begin{macro}{\lst@underbar}
% \begin{macro}{\lst@leftbrace}\begin{macro}{\lst@rightbrace}
% \begin{macro}{\lst@less}\begin{macro}{\lst@greater}
% \begin{macro}{\lst@vertical@bar}
% \begin{macro}{\lst@minus}\begin{macro}{\lst@multiply}
% Some definitions of special characters:
%    \begin{macrocode}
\def\lst@underbar{${_-}$}
\def\lst@leftbrace{$\{$}
\def\lst@rightbrace{$\}$}
\def\lst@less{$<$}
\def\lst@greater{$>$}
\def\lst@vertical@bar{$|$}
\def\lst@minus{$-$}
\def\lst@multiply{$*$}
%    \end{macrocode}
% \end{macro}\end{macro}\end{macro}\end{macro}
% \end{macro}\end{macro}\end{macro}\end{macro}
%
% \begin{macro}{\lst@string@blank}
% We define the macro for \stringblank. Temporary a blank space
% becomes other (catcode). Then we get the result by selecting a
% typewriter font.
%    \begin{macrocode}
\begingroup
\catcode`\ =12%
\gdef\lst@string@blank{{\ttfamily }}%
\endgroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@ChangeCatcodes}
% Now begins the horrible part: It is necessary to change many
% catcodes. Since we need backslash and braces with other meanings,
% we replace them by the slash $/$, $($ and $)$. Other characters like
% \$ and \& need not to be replaced, because we don't need them for
% defining macros, but $\backslash$, $\{$ and $\}$ are essential for
% doing that.
%    \begin{macrocode}
\begingroup
\catcode `/=0       \catcode `(= 1      \catcode `)=2 % new \, { and }
\catcode`\<=\active \catcode`\>=\active \catcode`\|=\active
\catcode`\-=\active \catcode`\*=\active
\catcode`\{=\active \catcode`\}=\active \catcode`\\=\active
%    \end{macrocode}
% From now on we must use the slash and $()$ instead of backslash and
% braces. Since the blank space will also be an active character, we
% must terminate each line with a comment character. Otherwise \TeX{}
% would think, we want to typeset something before beginning the
% document.
% \SpecialEscapechar/
%    \begin{macrocode}
/catcode`/ =/active%
/gdef/lst@active@blank(/ )%
%    \end{macrocode}
% The following macro changes catcodes and the definition of active
% characters at the time we input a listing.
% \SpecialEscapechar/
%    \begin{macrocode}
/gdef/lst@ChangeCatcodes(%
/catcode`/ =/active/let =/lst@active@blank%
/catcode`/\=/active/def\($/backslash$)%
/catcode`/{=/active/def{(/lst@leftbrace)%
/catcode`/}=/active/def}(/lst@rightbrace)%
/catcode`/<=/active/def<(/lst@less)%
/catcode`/>=/active/def>(/lst@greater)%
/catcode`/|=/active/def|(/lst@vertical@bar)%
/catcode`/-=/active/def-(/lst@minus)%
/catcode`/*=/active/def*(/lst@multiply)%
/chardef~="7E%
%    \end{macrocode}
% A tabulator (ASCII code 9=ord(I)$-$64) gets the catcode of a
% \TeX{}-tabulator.
% \SpecialEscapechar/
%    \begin{macrocode}
/catcode`/^^I=4%
%    \end{macrocode}
% Some characters are treated as other characters (12) or as letters
% (11).
% \SpecialEscapechar/
%    \begin{macrocode}
/catcode`/$=12/catcode`/&=12/catcode`/#=/lst@sharp@catcode%
/catcode`/^=12/catcode`/%=12/catcode`/"=12%
/catcode`/1=11/catcode`/2=11/catcode`/3=11%
/catcode`/4=11/catcode`/5=11/catcode`/6=11%
/catcode`/7=11/catcode`/8=11/catcode`/9=11%
/catcode`/0=11/catcode`/_=11)%
/endgroup
%    \end{macrocode}
% All changed catcodes (time of definition) are restored by ending the
% group.
% \end{macro}
%
%
% \subsection{Initialization}\label{ssInitialization}
% Defaults are selected and the user defined options are processed.
%    \begin{macrocode}
\normallisting
\listingtrue
\lst@tab@length=4
\ExecuteOptions{blank}
\ProcessOptions
%</package>
%    \end{macrocode}
%
%
% \section{Language driver files}\label{sLanguageDriverFiles}
%
% Each driver file contain language specific values:
% \begin{itemize}
% \item keywords;
% \item whether the language is case sensitive or not;
% \item comment lines and other comments;
% \item the stringizer;
% \item define \verb!\lst@sharp@catcode! to be 11, if it is used for
%	reserved words (compiler directives in C and C++), otherwise 12.
% \item \verb!\lst@PreProcessLine! is intend to manipulate the input
%	before the normal line processing takes place. Fortran 90 uses it
%	to detect comment lines beginning with '$*$' or 'C' and Eiffel's
%	string concatenate mechanism is done there.
% \end{itemize}
% This package selects a language by calling a macro \verb!\lst@! with
% the name of the language as suffix, e.g.\ \verb!\lst@fortran!. That
% macro must assign the values described above.
% The supported languages follow as examples.
%
%
% \subsection*{Blank listing}
% \begin{macro}{\lst@blank}
% For a blank listing we let all empty. \cs{makeatletter} lets \verb!@!
% be a letter here. Otherwise we can't access, e.g. \verb!lst@blank!.
%    \begin{macrocode}
%<*blank>
\makeatletter %
\gdef\lst@blank{%
    \keywords{}%
    \sensitivetrue %
    \DeclareCommentLine\relax %
    \DeclareSingleComment stuff \relax %
    \stringizer{} %
    \chardef\lst@sharp@catcode=12 %
    \let\lst@PreProcessLine=\lst@PreProcessLineDefault}%
\makeatother %
%</blank>
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{C listing}
% \begin{macro}{\lst@keywords@c}
% For C we first define the reserved words.
%    \begin{macrocode}
%<*c>
\makeatletter %
\gdef\lst@keywords@c{auto,break,case,char,const,continue,default,do,%
  double,else,enum,extern,float,for,goto,if,int,long,register,return,%
  short,signed,sizeof,static,struct,switch,typedef,union,unsigned,%
  void,volatile,while}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@special@c}
% To define C (and C++) directives as keywords the catcode of $\#$ must
% be changed from 'parameter symbol for macros' to 'letter'.
%    \begin{macrocode}
\begingroup \catcode`\#=11 %
\gdef\lst@special@c{#define,#elif,#else,#endif,#error,#if,#ifdef,%
    #ifndef,#line,#include,#pragma,#undef}%
\endgroup %
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@c}
% Since $*$ will be an active character when we input a listing, we
% have to change the catcode here. We also change the catcode of a
% double quote for compatibility with the german style file.
%    \begin{macrocode}
\begingroup %
\catcode`\*=\active \catcode`\"=12 %
\gdef\lst@c{\keywords{}%
    \morekeywords{\lst@keywords@c,\lst@special@c}%
    \sensitivetrue %
    \DeclareCommentLine\relax %
    \DeclareSingleComment /* */\relax %
    \stringizer{"}%
    \chardef\lst@sharp@catcode=11 %
    \let\lst@PreProcessLine=\lst@PreProcessLineDefault}%
\endgroup %
\makeatother %
%</c>
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{C++ listing}
% \begin{macro}{\lst@keywords@cpp}
% Since C++ is a extension of C (from the point of view here), we load
% the C driver file and define the additional keywords.
%    \begin{macrocode}
%<*cpp>
\clisting %
\makeatletter %
\begingroup \catcode`\_=11
\gdef\lst@keywords@cpp{asm,catch,class,const_cast,delete,dynamic_cast,%
  friend,inline,namespace,new,operator,private,protected,public,%
  reinterpret_cast,static_cast,template,this,throw,try,typeid,%
  virtual,xalloc,__multiple_inheritance,__single_inheritance,%
  __virtual_inheritance}%
\endgroup %
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@cpp}
% Again some catcodes are changed temporary to define a comments and
% stringizer.
%    \begin{macrocode}
\begingroup %
\catcode`\*=\active \catcode`\"=12 %
\gdef\lst@cpp{\keywords{}%
  \morekeywords{\lst@keywords@c,\lst@special@c,\lst@keywords@cpp}%
  \sensitivetrue %
  \stringizer{"}%
  \DeclareCommentLine //\relax %
  \DeclareSingleComment /* */\relax %
  \chardef\lst@sharp@catcode=11 %
  \let\lst@PreProcessLine=\lst@PreProcessLineDefault}%
\endgroup %
\makeatother %
%</cpp>
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{Eiffel listing}
% \begin{macro}{\lst@keywords@eiffel}\begin{macro}{\lst@eiffel}
% We begin as above.
%    \begin{macrocode}
%<*eiffel>
\makeatletter %
\gdef\lst@keywords@eiffel{alias,all,and,as,BIT,BOOLEAN,CHARACTER,%
    check,class,creation,Current,debug,deferred,do,DOUBLE,else,elseif,%
    end,ensure,expanded,export,external,false,feature,from,frozen,if,%
    implies,indexing,infix,inherit,inspect,INTEGER,invariant,is,like,%
    local,loop,NONE,not,obsolete,old,once,or,POINTER,prefix,REAL,%
    redefine,rename,require,rescue,Result,retry,select,separate,%
    STRING,strip,then,true,undefine,unique,until,variant,when,xor}%
\begingroup %
\catcode`\-=\active \catcode`\"=12%
\gdef\lst@eiffel{\keywords{}%
    \morekeywords{\lst@keywords@eiffel}%
    \sensitivetrue %
    \DeclareCommentLine --\relax %
    \DeclareSingleComment stuff \relax %
    \stringizer{"}%
    \chardef\lst@sharp@catcode=12 %
    \let\lst@PreProcessLine=\lst@PreProcessLine@eiffel}%
\endgroup %
%    \end{macrocode}
% \end{macro}\end{macro}
%
% Since '$\%$' continues a string, we need a different comment
% character and let the percent be other (catcode) to look for it.
%    \begin{macrocode}
\begingroup %
\catcode`\&=14 \catcode`\%=12 &
%    \end{macrocode}
% \begin{macro}{\lst@PreProcessLine@eiffel}
% \begin{macro}{\lst@PreProcessLine@TestPercent}
% If a string started on a preceding line, we test for the percent.
% Refer how we cut a line into a comment and other source code.
%    \begin{macrocode}
\gdef\lst@PreProcessLine@eiffel{&
  \if@lst@string &
      \expandafter\lst@PreProcessLine@TestPercent\lst@line%\relax &
  \fi}&
\gdef\lst@PreProcessLine@TestPercent#1%#2\relax{&
    \def\test{#2}&
    \ifx\test\empty \lst@PreProcessLineDefault &
        \else \expandafter\lst@PreProcessLine@CutPercent\lst@line\relax&
    \fi}&
%    \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@PreProcessLine@CutPercent}
% To output the characters in front of the percent we temporary switch
% the string boolean. Atferwards we redefine the input line, so that
% the normal line processing continues the string.
%    \begin{macrocode}
\gdef\lst@PreProcessLine@CutPercent#1%#2\relax{&
    \@lst@stringfalse \lst@Tokenize#1\relax &
    \@lst@stringtrue \def\lst@line{%#2}}&
\endgroup %
\makeatother %
%</eiffel>
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{Fortran 90 listing}
% \begin{macro}{\lst@keywords@fortran}\begin{macro}{\lst@fortran}
% Again the same \ldots
%    \begin{macrocode}
%<*fortran>
\makeatletter %
\gdef\lst@keywords@fortran{ACCESS,ACTION,ADVANCE,ALLOCATE,ALLOCATABLE,%
    ASSIGN,ASSIGNMENT,BACKSPACE,BLANK,BLOCK,CALL,CASE,CHARACTER,CLOSE,%
    COMMON,COMPLEX,CONTAINS,CONTINUE,CYCLE,DATA,DEALLOCATE,DEFAULT,%
    DELIM,DIMENSION,DIRECT,DO,DOUBLE,ELSE,END,ENDFILE,ENTRY,EOR,%
    EQUIVALENCE,ERR,EXIST,EXIT,EXTERNAL,FILE,FMT,FORM,FORMAT,%
    FORMATTED,FUNCTION,GO,TO,IF,IMPLICIT,IN,NONE,INOUT,INQUIRE,%
    INTEGER,INTENT,INTERFACE,INTRINSIC,IOLENGTH,IOSTAT,KIND,LEN,%
    LOGICAL,MODULE,NAME,NAMED,NAMELIST,NEXTREC,NMT,NULLIFY,NUMBER,%
    ONLY,OPEN,OPENED,OPERATOR,OPTIONAL,OUT,PAD,PARAMETER,PAUSE,%
    POINTER,POSITION,PRECISION,PRINT,PRIVATE,PROGRAM,PUBLIC,READ,%
    READWRITE,REAL,REC,RECL,RECURSIVE,RESULT,RETURN,REWIND,SELECT,%
    SEQUENCE,SEQUENTIAL,SIZE,STAT,STATUS,STOP,SUBROUTINE,TARGET,THEN,%
    TYPE,UNFORMATTED,UINT,USE,WHERE,WHILE,WRITE}%
\begingroup \catcode`\"=12%
\gdef\lst@fortran{\keywords{}%
    \morekeywords{\lst@keywords@fortran}%
    \sensitivetrue %
    \DeclareCommentLine !\relax %
    \DeclareSingleComment stuff \relax %
    \stringizer{"}%
    \chardef\lst@sharp@catcode=12 %
    \let\lst@PreProcessLine=\lst@PreProcessLine@fortran}%
\endgroup %
%    \end{macrocode}
% \end{macro}\end{macro}
%
% \begin{macro}{\lst@PreProcessLine@fortran}
% We use the \verb!\lst@PreProcessLine! mechanism to handle '$*$' and
% 'C' comments. The defined test macro tests, if the first character of
% the input line is a star or an uppercase c. In that case we output
% the line as comment and empty the input. That's all.
%    \begin{macrocode}
\def\lst@PreProcessLine@fortran{%
    \expandafter\lst@TestSpecialComment@fortran\lst@line\relax}%
\begingroup \catcode`\*=\active %
\long\gdef\lst@TestSpecialComment@fortran#1#2\relax{%
  \ifx #1*%
      \@lst@commenttrue \expandafter\lst@Tokenize\lst@line\relax %
      \let\lst@line=\empty \@lst@commentfalse %
  \else \if #1C%
      \@lst@commenttrue \expandafter\lst@Tokenize\lst@line\relax %
      \let\lst@line=\empty \@lst@commentfalse %
  \fi\fi}%
\endgroup %
\makeatother %
%</fortran>
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{Java listing}
% \begin{macro}{\lst@keywords@java} \begin{macro}{\lst@java}
% Nothing new \ldots
%    \begin{macrocode}
%<*java>
\makeatletter %
\gdef\lst@keywords@java{abstract,boolean,break,byte,case,catch,char,%
  class,const,continue,default,do,double,else,extends,final,%
  finally,float,for,goto,if,implements,import,instanceof,int,%
  interface,long,native,new,null,package,private,protected,public,%
  return,short,static,super,switch,synchronized,this,throw,throws,%
  transient,try,void,volatile,while,true,false}%
\begingroup %
\catcode`\*=\active \catcode`\"=12 %
\gdef\lst@java{\keywords{}%
  \morekeywords{\lst@keywords@java}%
  \sensitivetrue %
  \stringizer{"}%
  \DeclareCommentLine //\relax %
  \DeclareSingleComment /* */\relax %
  \chardef\lst@sharp@catcode=11 %
  \let\lst@PreProcessLine=\lst@PreProcessLineDefault}%
\endgroup %
\makeatother %
%</java>
%    \end{macrocode}
% \end{macro}\end{macro}
%
%
% \subsection*{Modula-2 listing}
% \begin{macro}{\lst@keywords@modula}\begin{macro}{\lst@modula}
% Once again the keywords first, \ldots
%    \begin{macrocode}
%<*modula>
\makeatletter %
\gdef\lst@keywords@modula{AND,ARRAY,BEGIN,BY,CASE,CONST,DIV,DO,ELSE,%
    ELSIF,END,EXIT,EXPORT,FOR,FROM,IF,IMPLEMENTATION,IMPORT,IN,MOD,%
    MODULE,NOT,OF,OR,POINTER,PROCEDURE,QUALIFIED,RECORD,REPEAT,RETURN,%
    SET,THEN,TYPE,UNTIL,VAR,WHILE,WITH,ABS,BITSET,BOOLEAN,CAP,%
    CARDINAL,CHAR,CHR,DEC,EXCL,FALSE,FLOAT,HALT,HIGH,INC,INCL,INTEGER,%
    LONGCARD,LONGINT,LONGREAL,MAX,MIN,NIL,ODD,ORD,PROC,REAL,SIZE,TRUE,%
    TRUNC,VAL}%
\begingroup %
\catcode`\*=\active \catcode`\*=12 %
\gdef\lst@modula{\keywords{}%
    \morekeywords{\lst@keywords@modula}%
    \sensitivetrue %
    \DeclareCommentLine\relax %
    \DeclareNestedComment (* *)\relax %
    \stringizer{'"}%
    \chardef\lst@sharp@catcode=12 %
    \let\lst@PreProcessLine=\lst@PreProcessLineDefault}%
\endgroup %
\makeatother %
%</modula>
%    \end{macrocode}
% \end{macro}\end{macro}
%
%
% \subsection*{Pascal listing}
% \begin{macro}{\lst@keywords@pascal}
% It's all the same, the keywords:
%    \begin{macrocode}
%<*pascal>
\makeatletter %
\gdef\lst@keywords@pascal{alfa,and,array,begin,boolean,byte,case,%
    char,const,div,do,downto,else,end,false,file,for,function,get,%
    goto,if,in,integer,label,maxint,mod,new,not,of,or,pack,packed,%
    page,program,procedure,put,read,readln,real,record,repeat,reset,%
    rewrite,set,text,then,to,true,type,unpack,until,var,while,with,%
    write,writeln}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lst@pascal}
% It's not all the same. We have to change some catcodes to declare
% Pascal comments: The braces are temporary replaced by the brackets.
%    \begin{macrocode}
\begingroup %
\catcode`\[=1 \catcode`\]=2 %
\catcode`\{=\active \catcode`\}=\active %
\catcode`\*=\active %
%    \end{macrocode}
% Now we can define \verb!\lst@pascal!.
%    \begin{macrocode}
\gdef\lst@pascal[\keywords[]%
    \morekeywords[\lst@keywords@pascal]%
    \sensitivefalse %
    \DeclareCommentLine\relax %
    \DeclareDoubleComment (* *) { }\relax %
    \stringizer[']%
    \chardef\lst@sharp@catcode=12 %
    \let\lst@PreProcessLine=\lst@PreProcessLineDefault]%
\endgroup %
\makeatother %
%</pascal>
%    \end{macrocode}
% \end{macro}
%
%
% \subsection*{Pascal XSC listing}
% \begin{macro}{\lst@keywords@pxsc}\begin{macro}{\lst@pxsc}
% Tell me, if you want more words to be keywords.
%    \begin{macrocode}
%<*pxsc>
\pascallisting %
\makeatletter %
\gdef\lst@keywords@pxsc{dynamic,external,forward,global,module,nil,%
    operator,priority,sum,type,use,dispose,mark,page,release,%
    cimatrix,cinterval,civector,cmatrix,complex,cvector,dotprecision,%
    imatrix,interval,ivector,rmatrix,rvector,string,im,inf,re,sup,%
    chr,comp,eof,eoln,expo,image,ival,lb,lbound,length,loc,mant,%
    maxlength,odd,ord,pos,pred,round,rval,sign,substring,succ,trunc,%
    ub,ubound}%
\begingroup %
\catcode`\[=1 \catcode`\]=2 %
\catcode`\{=\active \catcode`\}=\active %
\catcode`\*=\active %
\gdef\lst@pxsc[\keywords[]%
    \morekeywords[\lst@keywords@pascal,\lst@keywords@pxsc]%
    \sensitivefalse %
    \DeclareCommentLine\relax %
    \DeclareDoubleComment (* *) { }\relax %
    \stringizer[']%
    \chardef\lst@sharp@catcode=12 %
    \let\lst@PreProcessLine=\lst@PreProcessLineDefault]%
\endgroup %
\makeatother %
%</pxsc>
%    \end{macrocode}
% \end{macro}\end{macro}
%
%
% \subsection*{Turbo Pascal listing}
% \begin{macro}{\lst@keywords@tp}\begin{macro}{\lst@tp}
% The keywords are the reserved words and predefined functions and
% procedures of Turbo Pascal 6.0. It's a long list \ldots
%    \begin{macrocode}
%<*tp>
\makeatletter %
\gdef\lst@keywords@tp{and,array,asm,begin,case,const,constructor,%
  destructor,div,do,downto,else,end,file,for,function,goto,if,%
  implementation,in,inline,interface,label,mod,nil,not,object,of,or,%
  packed,procedure,program,record,repeat,set,shl,shr,string,then,to,%
  type,unit,until,uses,var,while,with,xor,%
  Abs,Addr,ArcTan,Chr,Concat,Copy,Cos,CSeg,DiskFree,DiskSize,%
  DosExitCode,DosVersion,DSeg,EnvCount,EnvStr,Eof,Eoln,Exp,FExpand,%
  FilePos,FileSize,Frac,FSearch,GetBkColor,GetColor,GetDefaultPalette,%
  GetDriverName,GetEnv,GetGraphMode,GetMaxMode,GetMaxX,GetMaxY,%
  GetModeName,GetPaletteSize,GetPixel,GetX,GetY,GraphErrorMsg,%
  GraphResult,Hi,ImageSize,InstallUserDriver,InstallUserFont,Int,%
  IOResult,KeyPressed,Length,Lo,MaxAvail,MemAvail,MsDos,Odd,Ofs,Ord,%
  OvrGetBuf,OvrGetRetry,ParamCount,ParamStr,Pi,Pos,Pred,Ptr,Random,%
  ReadKey,Round,SeekEof,SeekEoln,Seg,SetAspectRatio,Sin,SizeOf,Sound,%
  SPtr,Sqr,Sqrt,SSeg,Succ,Swap,TextHeight,TextWidth,Trunc,TypeOf,%
  UpCase,WhereX,WhereY,%
  Append,Arc,Assign,AssignCrt,Bar,Bar3D,BlockRead,BlockWrite,ChDir,%
  Circle,ClearDevice,ClearViewPort,Close,CloseGraph,ClrEol,ClrScr,Dec,%
  Delay,Delete,DelLine,DetectGraph,Dispose,DrawPoly,Ellipse,Erase,Exec,%
  Exit,FillChar,FillEllipse,FillPoly,FindFirst,FindNext,FloodFill,%
  Flush,FreeMem,FSplit,GetArcCoords,GetAspectRatio,GetDate,%
  GetDefaultPalette,GetDir,GetCBreak,GetFAttr,GetFillSettings,GetFTime,%
  GetImage,GetIntVec,GetLineSettings,GetMem,GetPalette,GetTextSettings,%
  GetTime,GetVerify,GetViewSettings,GoToXY,Halt,HighVideo,Inc,%
  InitGraph,Insert,InsLine,Intr,Keep,Line,LineRel,LineTo,LowVideo,Mark,%
  MkDir,Move,MoveRel,MoveTo,MsDos,New,NormVideo,NoSound,OutText,%
  OutTextXY,OvrClearBuf,OvrInit,OvrInitEMS,OvrSetBuf,PackTime,PieSlice,%
  PutImage,PutPixel,Randomize,Read,ReadLn,Rectangle,Release,Rename,%
  Reset,RestoreCrtMode,Rewrite,RmDir,RunError,Sector,Seek,%
  SetActivePage,SetAllPalette,SetBkColor,SetCBreak,SetColor,SetDate,%
  SetFAttr,SetFillPattern,SetFillStyle,SetFTime,SetGraphBufSize,%
  SetGraphMode,SetIntVec,SetLineStyle,SetPalette,SetRGBPalette,%
  SetTextBuf,SetTextJustify,SetTextStyle,SetTime,SetUserCharSize,%
  SetVerify,SetViewPort,SetVisualPage,SetWriteMode,Sound,Str,%
  SwapVectors,TextBackground,TextColor,TextMode,Truncate,UnpackTime,%
  Val,Window,Write,WriteLn}%
\begingroup %
\catcode`\[=1 \catcode`\]=2 %
\catcode`\{=\active \catcode`\}=\active %
\catcode`\*=\active %
\gdef\lst@pxsc[\keywords[]%
    \morekeywords[\lst@keywords@tp]%
    \sensitivefalse %
    \DeclareCommentLine\relax %
    \DeclareDoubleComment (* *) { }\relax %
    \stringizer[']%
    \chardef\lst@sharp@catcode=12 %
    \let\lst@PreProcessLine=\lst@PreProcessLineDefault]%
\endgroup %
\makeatother %
%</tp>
%    \end{macrocode}
% \end{macro}\end{macro}
%
%
% \section{Samples}
%
% This documentation uses some files to illustrate the listings package.
% Here they are:
%    \begin{macrocode}
%<*listing1>
    switch (direction)
    {// choose direction
        case backward     : { ... break; }
        case backwarddown : { ... break; }
        case up           : { ... break; }
        case forwardup    : { ... break; }
    }

    const char* string = "Strings  are supported.";
%</listing1>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*listing2>
    for i:=maxint downto 0 do
    begin
        { we do
          nothing }
    end;

    WriteLn('Pascal keywords are');
    writeln('not case sensitive.');
%</listing2>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*listing3>
    if (ThereIsALongLine) { ItExceedsASingleLineInTheListing(); }
%</listing3>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*listing4>
    (* ------------------------------ *)
    (* A short test for Pascal option *)
    (*  (not for a Pascal compiler)   *)
    (* ------------------------------ *)

  (* Since comments can't be nested,
     (* this comment ends right after this *)
     and not here *)

  (* But using the braces like { these here } will work *)
  { And doing it (* the other way round also }

  'A String without any context'
  'This is a string (* and not a comment'
  'This is a String (* and not a comment' *)
  'This is a String { and not a comment'

  { This is a comment '''and not a string'' }
%</listing4>
%    \end{macrocode}
%
%
% \section{Extensions}\label{sExtensions}
%
% For an additional language first declare a new option and define a
% language command. Refer the supported languages for examples. Then
% add a driver file. Refer the last section how this is done.
%
% \DescribeMacro\lst@CommentLine
% \DescribeMacro\lst@SOC \DescribeMacro\lst@EOC
% If you want comment lines or comments, which are not supported by
% the declaration commands of this package, you have a problem.
% Contact me or follow these steps:
% \begin{enumerate}
% \item Define the macro, which cuts up the input line into a comment
%	line and the noncomment rest: The macro gets the input via the
%	macro \verb!\lst@line!. After the call \verb!\lst@line! must hold
%	the noncomment rest and \verb!\lst@commentline! the comment line.
%	The C++ line
% \begin{verbatim}
%    if (comments!=appear) // comment stuff\end{verbatim}
%	must be cut into '\verb|if (comments!=appear) |' and
%	'\verb!// comment stuff!'.
% \item Define the macro, which finds the start of a comment:
%	The macro gets the input via the macro \verb!\lst@line!. After
%	the call \verb!\lst@line! must contain the source line upto the
%	first appearance of a comment (exclusive). The comment and might
%	the rest of the line must be in the macro \verb!\lst@comment!.
%	If a comment is separated (not if and only if), you have to call
%       \verb!\@lst@commenttrue!. The Pascal line
% \begin{verbatim}
%    if { comment } appears then\end{verbatim}
%	is cut into '\verb!if !' and '\verb!{ comment } appears then!'.
% \item Define the macro, which finds the end of a comment:
%	The macro gets the input via the macro \verb!\lst@line!. After
%	the call \verb!\lst@comment! must hold the comment and
%	\verb!\lst@line! the noncomment rest of the line (which might be
%	empty, of course). If the end of comment is found, you have to call
%	\verb!\@lst@commentfalse!. The Pascal line
% \begin{verbatim}
%    { comment } appears then\end{verbatim}
%	must be cut into '\verb!{ comment }!' and '\verb! appears then!'.
% \end{enumerate}
% Assign these macros to \verb!\lst@CommentLine!, \verb!\lst@SOC! and
% \verb!\lst@EOC! within your language command.
%
%
% \section{History}\label{sHistory}
% \begin{itemize}
% \item[0.1] from 1996/03/09
%	\begin{itemize}
%	\item test version to look whether package is possible or not
%	\end{itemize}
% \item[0.11] from 1996/08/19
%	\begin{itemize}
%	\item additional blank option
%	\item	\cs{keywords}, \cs{morekeywords}, \cs{keywordstyle}
%		and \cs{commentstyle} are new commands
%	\item implementation guide improved and user's guide updated
%	\item alignment improved by rewriting some macros
%	\end{itemize}
% \item[0.12] from 1997/01/16
%	\begin{itemize}
%	\item nearly perfect alignment now
%	\item \cs{stringizer}, \cs{stringstyle}, \cs{prelisting}
%		and \cs{postlisting} are new
%	\item user selection \cs{listingtrue} and \cs{listingfalse} possible
%	\item \cs{blankstringtrue} and \cs{blankstringfalse} handle output
%		of blanks in strings
%	\item package supports tabulators now; new command \cs{tablength}
%	\end{itemize}
% \item[0.13] from 1997/02/11
%	\begin{itemize}
%	\item additional languages: Eiffel, Fortran 90, Modula-2, Pascal XSC
%	\item load on demand: language specific macros have been moved to
%		driver files
%	\item comments are declared now and not implemented for each language
%		again (this makes these \TeX{} sources easier to read)
%	\item 'string exceeds line' test moved to
%		\verb!\lst@PreProcessLineDefault!
%	\item sample files moved to .dtx-file
%	\end{itemize}
% \item[0.14] from 1997/02/18
%	\begin{itemize}
%	\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 qoutes
%	\item comment declaration is user-accessible now
%	\item package compatible to \verb!german.sty! now
%	\item changed some identifiers
%	\end{itemize}
% \item[0.15] from 1997/04/18
%	\begin{itemize}
%	\item listing environment is new
%	\item additional languages: Java, Turbo Pascal
%   \item \verb!\lst@width! changes from 0.65em to 0.8em for Fortran 90
%   \item corrected some mistakes in the documentation
%	\item package renamed from listing.dtx to listings.dtx, since there
%		is already a listing package
%	\end{itemize}
% \end{itemize}
%
%
% \begin{thebibliography}{9}
% \bibitem{Eiffel}
%       \textsc{Bertrand Meyer}: \textbf{Eiffel: the language}\\
%       Prentice Hall International (UK) Ldt, 1992;
%       ISBN 0-13-247925-7
% \bibitem{Fortran}
%       \textsc{Thomas Michel}: \textbf{Fortran 90: Lehr-- und Handbuch}\\
%       Mannheim; Leipzig; Wien; Z\"urich: BI-Wiss.-Verlag, 1994;
%       ISBN 3-411-16861-7
% \bibitem{Modula}
%       \textsc{Niklaus Wirth}: \textbf{Programmieren in Modula-2},
%       \"Ubers.\ Guido Pfeiffer\\
%       2.\ Auflage -- Berlin; Heidelberg; New York; London; Paris; Tokyo;
%               Hong Kong: Springer, 1991;
%       ISBN 3-540-51689-1
% \bibitem{java} \texttt{http://java.sun.com}
% \bibitem{verbatim}
%       \textsc{Rainer Sch\"opf, Bernd Raichle, Chris Rowley}:
%       \textbf{A New Implementation of \LaTeX's \texttt{verbatim}
%           and \texttt{verbatim*} Environments.}
% \end{thebibliography}
%
%
% \setcounter{IndexColumns}{2}
% \PrintIndex
%
%
% \Finale
%
\endinput
