LISTINGS.DTX Version 0.17

\begin{matrix}c \\ ◯ \end{matrix} 1996–1997 by Carsten Heinz

Contents

1 User’s guide 2 1.1 Introduction . . . . . . . . 2 1.2 Installation . . . . . . . . 3 1.3 Selecting a language … 3 1.4 Typesetting a listing … 5 1.5 Figure out the appearance 6 1.6 Other languages . . . . . 8 1.7 Troubleshooting . . . . . . 9 1.8 It’s not all fine . . . . . . 10

2 How the package works 11 2.1 The main idea . . . . . . 11 2.2 Line processing . . . . . . 12 2.3 Tokenizing . . . . . . . . . 13 2.4 Special characters . . . . . 13

3 General TEXniques 14 3.1 Macro parameter parsing 14 3.2 Quick ’if parameter empty’ 15

4 Implementation 16 4.1 Registers and variables . . 16 4.2 Comments . . . . . . . . . 17 4.3 Keywords . . . . . . . . . 21 4.4 Commands . . . . . . . . 22 4.5 Typesetting a listing … 24 4.6 Line processing . . . . . . 27 4.7 Tokenizing . . . . . . . . . 29 4.8 Output . . . . . . . . . . 31 4.9 Special characters . . . . . 33 4.10 Initialization . . . . . . . 35

5 Language driver files 35 5.1 Blank listing . . . . . . . 35 5.2 Ada . . . . . . . . . . . . 36 5.3 Algol . . . . . . . . . . . . 36 5.4 C . . . . . . . . . . . . . . 39 5.5 C++ . . . . . . . . . . . . 40 5.6 Cobol . . . . . . . . . . . 40 5.7 Comal 80 . . . . . . . . . 42 5.8 Eiffel . . . . . . . . . . . . 43 5.9 Elan . . . . . . . . . . . . 44 5.10 Fortran . . . . . . . . . . 45 5.11 Java . . . . . . . . . . . . 46 5.12 Lisp . . . . . . . . . . . . 46 5.13 Logo . . . . . . . . . . . . 47 5.14 Matlab . . . . . . . . . . . 48 5.15 Modula-2 . . . . . . . . . 50 5.16 Oberon-2 . . . . . . . . . 50 5.17 Pascal . . . . . . . . . . . 51 5.18 Pascal XSC . . . . . . . . 51 5.19 Turbo Pascal . . . . . . . 52 5.20 Perl . . . . . . . . . . . . 53 5.21 PL/I . . . . . . . . . . . . 54 5.22 Simula . . . . . . . . . . . 55 5.23 SQL . . . . . . . . . . . . 57 5.24 TEX . . . . . . . . . . . . 58

6 Extensions 63

7 History 64

INCOMPATIBLE CHANGES have been made from version 0.16 to version 0.17. The commands \blanklisting, \clisting, … have been removed. Languages are selected with the command \selectlisting. The command \labelstyle has a new syntax and semantics. These features are described on page 3 and 7, respectively. Sorry, but now it’s possible to add languages without changing the kernel listings.sty.

1 User’s guide

1.1 Introduction

You have a problem? You wanna typeset source code of a programming language within L^{A}TEX 2ε like

switch ( d i r e c t i o n )
{ // choose d i r e c t i o n
case backward  : { … break ; }
case backwarddown : { … break ; }
case up  : { … break ; }
}
for ( int i =0 ; i <1000 ; i ++)
{ // do something
i f ( i == i ) { i += 1 ; i −−; }
}

or

1  for i :=maxint downto 0 do
2  begin
3  { do nothing }
4  end;

5

6  WriteLn( ’ Pascal keywords are ’ ) ;
7  writeln ( ’ not case s e n s i t i v e . ’ ) ;

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 L^{A}TEX 2ε-file through your C++, Pascal 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 in 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!

1.2 Installation

The main files of this package are listings.dtx and listings.ins. Run the latter file through TEX. This will create listings.sty and a couple of driver files with the prefix lst, e.g. lstfortran.sty, but the exact name is system dependent. Copy all created .sty-files to a directory searched by TEX. This completes the installation. Run listings.dtx through TEX to get the documentation

listings.dvi.

Important note: All files of the listings package 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.

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.

1.3 Selecting a language

\selectlisting You choose a language with \selectlisting. The argument is (nearly) one of the language names listed below. The driver files are loaded on demand. The command also has an optional argument to select different kinds of the same language, e.g.

    \selectlisting[1974]{cobol}

selects COBOL ANS-1974, whereas the default would be ANS-1985. All languages currently supported are listed together with the available options, where always the first option is default, i.e. selected if none is given. I also mention what the listings package is not capable of. ’???’ in driver files indicate things I don’t know. To help me: Please send me an e-mail with the languages and options you use (i.e. are tested in a way), languages and options you want to be corrected or want additionally. See section 1.8. Note: Language selection is local now.

Blank \selectlisting{blank}.

This is the default language: no keywords and no comments are detected (unless additional specified, see section 1.6).

Ada \selectlisting{ada}.

This package can’t handle strings where the usual quotation marks (double quotes) are replaced by percent characters.

Algol \selectlisting{algol}, options: 68, 60.

Algol 60 seems to be ok. But there are problems concerning the comments of Algol 68. First, comments enclosed by / c are not supported. Second, if you use a sharp # within co...co (and dito within comment), there must be a matching second #, or the output is not all right.^{1} The other way round, i.e. a lonely comment within #...# is harmless.

C \selectlisting{c}.
C++ \selectlisting{cpp}, options: ansi, vc (Visual C++).
Cobol \selectlisting{cobol}, options: 1985, 1974, ibm.

Keywords are not marked, if their names are broken in two parts, i.e. continued in the following line. Sometimes portions of a string are not printed as a string. This happens, if the double quote is not doubled to insert a quote, e.g. ""bad" cobol" won’t be printed correctly.

Comal 80 \selectlisting{comal}.
Eiffel \selectlisting{eiffel}.
Elan \selectlisting{elan}.
Fortran \selectlisting{fortran}, options: 90, 77.

The keywords are assumed to be not case sensitive.

Java \selectlisting{java}.
Lisp \selectlisting{lisp} (Common Lisp).
Logo \selectlisting{logo}.
Matlab \selectlisting{matlab}.

Matlab uses the quote with two meanings. This package always assumes the beginning or ending of a string, even if you use the quote as transposeconjugate operator.

Modula-2 \selectlisting{modula}.
Oberon-2 \selectlisting{oberon}.
Pascal \selectlisting{pascal}.
Pascal XSC \selectlisting{pxsc}.

Tell me, if you want more words to be keywords.

Turbo Pascal \selectlisting{tp}.

Keywords are from version 6.0. Possibly too many keywords present.

1The problem is the following: The sharp is a special character, whereas co is a predefined word and consists of letters. Comments enclosed by special characters are handled easily, and even comments starting or ending with keywords are possible (Algol 60). But a mixture of both (without matching sharp) can only be handled by changing the kernel listings.sty. Since that would slow down all other languages, I decided to do it this way (matching sharp). I even don’t know, if this way is standard Algol 68 — the books are not very detailed, or I haven’t found it.

Perl \selectlisting{perl}.
PL/I \selectlisting{pli}.
Simula 67 \selectlisting{simula}, options: 67, cii, dec, ibm.
SQL-92 \selectlisting{sql}.
TEX \selectlisting{tex}, options: plain, primitive, latex, allatex.

1.4 Typesetting a listing

\inputlisting The main command for this purpose is \inputlisting. The syntax is

    \inputlisting[FIRST,LAST]{WHOLE FILENAME}

where [FIRST,LAST] is optional and determines the range of lines to typeset. 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

    \inputlisting[3,10]{testfile.pas}

would print lines 3,4,…,10 of testfile.pas, if file and lines are present.

listing There is also a listing environment. It typesets the source code enclosed within \begin{listing} and \end{listing}. If the source code starts right after \begin{listing}, it is dropped upto the end of line. Dito the source preceding and following \end{listing} directly, i.e. in the same line. You may don’t like this, but the lines

       \selectlisting{fortran}
       \begin{listing}DROPPED
* This is a test for the listing environment
C and not considered to be an example for
   ! Fortran!
      Program example
      ...
DROPPED\end{listing}DROPPED

result in

∗ This is a t e s t for the l i s t i n g environment
C and not considered to be an example for
! Fortran !
Program example

…

\listingfalse Since typesetting listings with this package is possibly slow, you can suppress \listingtrue the output with \listingfalse. Afterwards this package only prints the name of

the source like

— Listing of testfile.pas has been skipped. —

\listingtrue reverses the effect.

\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.,

    \tablength{8}

i.e. tabulator stops are set at the columns 1, 9, 17, 25 … Negative values are prohibited. They won’t confuse this package, since it gives an error message and proceeds with the old value of tablength.

\listoflistings Two more commands should be mentioned here. Use \listoflistings as

\listlistingsname you do \listoftables and \listoffigures and renew \listlistingsname to

change the default header ’Listings’. The list shows either the filename or the optional argument of the listing environment, e.g.

    \inputlisting{Quicksort.pas}
    \begin{listing}[Heapsort]
    ...
    \end{listing}

will show the names ’Quicksort.pas’ and ’Heapsort’.

1.5 Figure out the appearance

You have some possibilities to change how the output looks like.

\keywordstyle By default keywords^{2} are typeset bold, comments in italic shape and strings \commentstyle using no special style. You can change this with the commands \keywordstyle,

\stringstyle  \commentstyle and \stringstyle, e.g.
    \keywordstyle{\bfseries\itshape} % bold and italic
    \commentstyle{\tt\small}         % LaTeX 2.09 typewriter, small
    \stringstyle{\ttfamily}          % typewriter

will typeset the second example of the introduction as follows

for i :=maxint downto 0 do

begin

          { do  nothing }

end ;

     WriteLn ( 'Pascal keywords are' ) ;
     writeln ( 'not case sensitive.' ) ;

\blankstringtrue Once again blank spaces of a string have been printed . Suppress this by using

\blankstringfalse  \blankstringtrue and switch to default with \blankstringfalse.

2Let’s talk about keywords: I tried to get all keywords of the languages, but there are so many books with no list of keywords. So I looked at the index, but some books print keywords bold and predefined functions in italics, other books print both in bold. So I had to guess, which words are keywords. Moreover it’s a great deal to find out whether the keywords are case sensitive or not. Of course, there are really fine books (e.g. [1]). And I know that some languages don’t have keywords, and so there can’t be a list of them. But even these languages have predefined words — which are not listed. Hence, for our purpose keywords are predefined words, fixed words, reserved words, real keywords and all words you or I want to name so.

\labelstyle By default no line numbers are printed. You can change this with the \labelstyle command. The syntax is

    \labelstyle[step]{the style}

The style determines how the line numbers look like (\ttfamily, \small, and so on). Line numbers are printed all ’step’ lines. More precisely all line numbers are printed, which are divisible by step. If step is zero, no line numbers will be typeset. The step is an optional argument. If no step is specified, it is assumed to be 1. Here some (exotic) examples:

   \labelstyle[3]{\ttfamily\small} % line 3,6,9,..., small typewriter
   \labelstyle{\small\oldstylenums}% small oldstyle numbers
   \makeatletter
   \labelstyle{\@roman} % roman numbers(!) each line
   \labelstyle{\@Roman} % upper case roman numbers
   \makeatother

The C++ source line

i f ( ThereIsALongLine ) { ItExceedsASingleLineInTheListing ( ) ; }

\spreadlisting gives rise to an overfull \hbox. To avoid things like that you can first spread \prelisting the width taken by a listing, and second change the fontsize. The commands

\postlisting  \spreadlisting, \prelisting and \postlisting have one argument each. For

the example above you should use

    \spreadlisting{1in} % spread the width by 1in, 0.5in left and right
    \prelisting{\small} % select new fontsize
    \postlisting{}      % nothing to do (default)

or something similar and get

i f ( ThereIsALongLine ) { ItExceedsASingleLineInTheListing ( ) ; }

You can use the pre-post-mechanism to add something right before a listing starts or after it ends, e.g. \prelisting{\bigbreak} will lead to an empty line between a listing and the preceding text (if on the same page).

\normallisting Changes made by the commands above are reset by \normallisting (there are no arguments): Keywords are typeset bold, comments in italic shape, stringstyle, labelstyle and pre- and postlisting are empty, blank spaces in strings are printed , and spreadlisting is set to 0pt. Nothing other is affected.

\lstlineskip The one and only argument of this command is a skip. It’s the additional

space between two lines in the output of a listing. The default is 0pt.

\lstbaseem Here is one more command, which should be used in driver files only, since the one and only parameter is language specific. But you can use it for adjustment in your document. The parameter gives the witdh one character takes in the output in units of 1em. The parameter is a floating number and not a TEX dimension, i.e. the unit em is added by the listings package. If you specify \lstbaseem{1}, i.e. 1em, characters will never overlap. And the output produced after \lstbaseem{0} looks quite funny. Better try values near 0.6.

1.6 Other languages

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.

Let’s say, we want to produce following output:

function Fib ( integer n ) : integer ;
// Function returns the n−th Fibonacci .

begin

i f ( n<2 ) then return 1 ;
else return Fib ( n−1)+Fib ( n−2 ) ;
end;
// Main program .

begin

print (” Fib ( 10 ) = ”, Fib ( 10 ) , ” \ n ”);
end.

You already know about \stringstyle and \blankstringfalse. We assume \selectlisting{blank}. And now comes all the rest to print such a language

\keywords mixture. To set the keywords use the \keywords command. After

    \keywords{one,two,three,four,five,six,seven,eight,nine,ten,
        eleven,twelve}

exactly these twelve keywords are present. As you see, each two keywords are

\morekeywords separated by a comma. If you want to add keywords only use \morekeywords like

    \morekeywords{maxreal,minreal} % add these keywords
    \morekeywords{zero,MAXINT}     % add also

\sensitivetrue Some languages are case sensitive, others are not. You can select this with

\sensitivefalse  \sensitivetrue and \sensitivefalse, respectively. This package will then use

the right keyword test.

\stringizer The command \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

    \catcode`\"=12
    \stringizer{'"}

The catcode is changed (locally) for compatibility with german.sty. The double quote is defined active there, but when we input a listing the double quote will have catcode 12 (=other). The stringizer command has an optional argument to select whether the stringizer is doubled (default, e.g. Pascal) or preceded by a backslash (e.g. C) to insert the stringizer itself at the current position. The arguments are d and b, respectively, e.g.

    \stringizer[d]{'} % doubled stringizer inserts stringizer
    \stringizer[b]{"} % backslashed stringizer inserts

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.

\DeclareCommentLine      \DeclareCommentLine has one parameter, which is terminated by \relax, i.e.
    \DeclareCommentLine //\relax

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 2.4 and 4.9. If you don’t want any comment lines, let the parameter empty, but don’t forget the \relax!

\DeclareSingleComment Four types of comments are supported: single for languages with one kind \DeclareDoubleComment of comment, e.g. C or C++; double for languages with two kinds of comments, \DeclareNestedComment e.g. Pascal comments enclosed within (* and *) and within { and }; nested for \DeclarePairedComment languages with one kind of comment, which can be nested, e.g. Modula-2. A

paired comment is a single comment, but the two comment delimiters are the same and therefore occur paired. The declaration of such comments is similar to comment lines. The character sequences are separated by one blank space, e.g.

    \DeclareSingleComment /* */\relax
    \DeclareDoubleComment (* *) { }\relax
    \DeclareNestedComment (* *)\relax
    \DeclarePairedComment #\relax

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 4.9. If you don’t want comments, let the second parameter of \DeclareSingleComment empty, i.e. type something like

␣␣␣␣\DeclareSingleComment␣stuff␣\relax

If a supported language already uses your favourite keywords, stringizer and/or comments, you are free to select that language and adjust only the wrong data.

1.7 Troubleshooting

After receiving an e-mail from Andreas Bartelt^{3} the idea comes up to write this section. It is intend to help you handling unusual situations.

• If you have problems using \inputlisting within L^{A}TEX environments or commands, put the listing in a \vbox.

3Andreas.Bartelt@Informatik.Uni-Oldenburg.DE

• A source line might exceeds the textwidth, as shown in section 1.5. Put the listing in a \hbox to decrease the logical width like

    \hbox to 3.5in{
        \vbox{\inputlisting{testfile.pas}}
        \hss}

The \hss avoids an overfull \hbox. You can use that construction together with \fbox to get something like

function Fib ( integer n ) : integer ;
// Function returns the n−th Fibonacci .

begin

i f ( n<2 ) then return 1 ;
else return Fib ( n−1)+Fib ( n−2 ) ;
end;

• The example just presented uses \inputlisting within an argument of a command like \fbox. It’s not possible with the listing environment! To go around this type

    \setbox0=\vbox{
    \begin{listing}
function Fib(integer n):integer;
...
    \end{listing}
    }% not on the same line as \end{listing}!
and then $$\fbox{\hbox to 3.5in{\box0\hss}}$$ to get the example.

1.8 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. Tell me, if you want additional languages or more options for a language already present. What’s about Delphi, Prolog or Reduce?

• If you use italic cmr fonts (comments), the dollar $ comes out as £. Change italic to slanted (\slshape) or don’t use cmr fonts.

• If you use \DeclarePairedComment, the first comment delimiter appears not in commentstyle, e.g. # comment #.

You’re not lucky about the listings package? You found errors? Damn and blast it or contact me:

cheinz@wmpi04.math.uni-wuppertal.de

2 How the package works

What happens when a user calls \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.

2.1 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

    if x=y then write('alignment')
           else print('alignment');

shouldn’t come out as

if x=y then write(’alignment’) else print(’alignment’);  or  if x=y then write(’alignment’) else print(’alignment’);

only because blank spaces are not wide enough or because a bold letter is wider 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:

i f  x = y  t h e n  w r i t e  …
e l s e  p r i n t  …

Going this way the alignment of columns can’t be disturbed. But if the boxes are not wide enaugh, we get

i f x=y then write …

And choosing the width so that the widest character fits in, leads to

i f x = y t h e n w r i t e …

Both are not acceptable. So there is more to do. Each input line will be cut up in units. Since we want to scan for keywords, this is no extra work. In the example the units are

if, x, =, y, then, write, …

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

i f  x = y  t h e n  w r i t e  …

Now we are ready to choose the base width of a box — that’s \lstbaseem. 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 \quad). At the moment most languages use the empirical value 0.6em. 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

\hbox.

2.2 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.

• First we pay attention on comments, which started in preceding lines, e.g.

         comment } for i:=1 to maxint do ...

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.

• 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.

• Afterwards we have to output the comment. But when we look for a comment, we don’t take notice of other things. Consider

         writeln('This is a string { and not a comment }');

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.

• If all strings are finished, we can output the comment, since it’s really a comment.

This is a sketch of line processing. For more detailed information see section 4.6, 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 separate this from finding a comment.

2.3 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 go to the next tabulator stop. The output routines are responsible for knowing the number of blanks we need.

If it’s any other nonletter, we gather all coming nonletter (upto the next letter, of course) and output these nonletter. Then we start with a letter again, …

2.4 Special characters

As you know some characters have a special meaning to TEX, e.g. the subscript _or the backslash \. TEX realizes this using so called category codes (catcodes). TEX knows sixteen different ones:

0 escape delimiter (backslash) \catcode`\\=0
1 beginning of a group ({)  \catcode`\{=1
2 ending of a group (})  \catcode`\}=2
3 mathematics shift ($)  \catcode`\$=3

            4 tabulator (&)  \catcode`\&=4

5 end of line (carriage return) \catcode`\^^M=5
6 macro parameter (#)  \catcode`\#=6

            7 superscript (^)  \catcode`\^=7
            8 subscript (_)  \catcode`\_=8
            9 ignore  \catcode`\^^@=9
           10 blank space  \catcode`\ =10

11 letter  A..Z,a..z
12 other
13 active (e.g. ~)

           14 comment  \catcode`\%=14

15 invalid characters

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 ~ or the double quote in german.sty).

We can’t change catcodes of characters, which TEX has already read. But we are able to change them before. After \catcode`\A=10 an upper ’A’ has the same effect as a blank space! Consider the TEXsource

    \def\uppera{A} % saving upper 'A'; we shouldn't use \upperA. Why?
    \catcode`\A=10 % 'A' becomes blank space. That's the reason!
    MayAbeAaAcuriousAexample. \upperaAnd it work's.

The output is

    May be a curious example. And it work's.

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 x1, 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 {. 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.

3 General TEXniques

3.1 Macro parameter parsing

A macro has at most nine parameters. They are numbered consecutively and are referenced by #1, …, #9. In the definition they appear after the macro name, e.g.

    \def\macro#1#2#3{\textbf{#1}\texttt{#2}\textit{#3}}

has three parameters. \macro the and \macro{t}{h}{e} both lead to the output ’the’. Parameters with more than one character must be enclosed in braces. If you call the macro with less than three parameters, you will get an error message (hopefully most times), since the three parameters are the calling syntax of the macro. That’s all well known.

But TEX’s macro processor is more powerful. Nearly any character sequence and parameter mixture can be used for the calling syntax, e.g.

    \def\macro z=(#1,#2){ ... }

The call \macro{10}{0} is illegal, but \macro z=(10,0) is ok. The parameters are ’10’ and ’0’, respectively.

This mechanism can be used to check whether a character sequence is a substring of another sequence — which will be used to extract comments and keywords, but this comes later. Consider

    \def\macro #1substring#2\relax{ ... }

If we call this macro, we should always add substring\relax at the end, since the sequence belongs to the syntax of the macro:

    \macro This is our first call.substring\relax

Here the second parameter of the macro will be empty, but using

    \macro This is a substring example.substring\relax

the second parameter is not empty, since the first ’substring’ terminates the first parameter and lets the second begin after (upto the closing \relax). The character sequence ’substring’ is a substring of the preceding character sequence, if and only if the second parameter is not empty.

Later we let the preceding character sequence be a list of keywords to test whether a character sequence is a keyword or not. Or we let the preceding character sequence be the current soure line and replace ’substring’ by ’//’ to look for a C++ comment line.

3.2 Quick ’if parameter empty’

There are many situations where you have to look whether a macro parameter is empty or not. Let’s say, we want to test the first parameter, which is refered by #1. The natural way would be something like

    \def\test{#1}%
    \ifx \test\empty %
            % #1 is empty
    \else %
            % #1 is not empty
    \fi %

where \empty is defined by \def\empty{}, of course. And now the mad way:

    \ifx \empty#1\empty %
            % #1 is empty
    \else %
            % #1 is not empty
    \fi %

Having an empty parameter the \empty left from #1 is compared with the \empty on the right. Since they are the same, it’s all ok. 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 paramater must not be the macro \empty, e.g.

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 \emptys 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 slows down the \ifx. Consider

    \def\test{#1}\ifx \test\empty \else \fi % natural

and

    \ifx \empty#1\empty \else \fi % mad

The mad version needs about 45% of the natural’s time.

4 Implementation

Before considering the implementation, here some conventions I used:

• The names of all public macros (the user commands) have lower case letters. (That’s not true: \DeclareCommentLine, …, but consistent with the third item.)

• The name of all private macros and variables have prefixes: lst@ for a general macro or variable, lstdrv@ when it is defined in a driver file, and lstenv@ if it is defined for the listing environment.

• 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@ProcessLine. (The only exception is the ’procedure-macro’

     \lst@ifoneof.)

4.1 Registers and variables

The current version needs 1 read register, 5 counters, 2 dimensions and 1 token register. The counter \@tempcnta and the dimension \@tempdima are also used, see the index.

\lst@inputfile \lst@ifendinput \iflisting  \iflisting is described in the user’s guide. The input file is \lst@inputfile.

The output of the file terminates, if and only if the boolean \lst@ifendinput is true.

1 ⟨∗package⟩

 2 \newif\iflisting
 3 \newread\lst@inputfile
 4 \def\lst@endinputtrue{\let\lst@ifendinput\iftrue}
 5 \def\lst@endinputfalse{\let\lst@ifendinput\iffalse}

\lst@lastno \lst@lineno The user specified last line and the current input line are kept in two counters:

 6 \newcount\lst@lastno \newcount\lst@lineno

\lst@ifcomment \lst@ifstring \lst@commentdepth Comments (not whole comment lines) and strings are indicated by following booleans. The current comment depth uses a counter.

 7 \newcount\lst@commentdepth
 8 \def\lst@commenttrue{\let\lst@ifcomment\iftrue}
 9 \def\lst@commentfalse{\let\lst@ifcomment\iffalse}
10 \def\lst@stringtrue{\let\lst@ifstring\iftrue}
11 \def\lst@stringfalse{\let\lst@ifstring\iffalse}

\lst@width \lst@length \lst@pos The dimension \lst@width holds the width of a single character box and is set to \lst@baseem em, when we output a listing. The counter \lst@length holds the length of the current character string we want to output. \lst@pos holds the current column number to handle tabulators.

12 \newdimen\lst@width \newcount\lst@length \newcount\lst@pos

\lst@halfspread That’s the half of spreadlisting’s argument.

13 \newdimen\lst@halfspread

\lst@line \lst@comment \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 \lst@line, \lst@comment and \lst@commentline. They hold the current

line, comment and comment line for line processing.

\lst@other This version gather non-alphanumeric characters before their output. Since these characters might expand, we need a token register to gather them, where they surely do not expand.

14 \newtoks\lst@other

4.2 Comments

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

\lst@CutCL use a macro like this:

    \def\lst@CutCL#1//#2\relax{%
        \def\lst@line{#1}\def\lst@commentline{//#2}}

The parameter definition ensures that the first parameter holds the code and our second paramater the comment upto a \relax, which marks the end of the source. We (re)define the input and comment line, where we must add the separator ’//’

\lst@CommentLine again. That’s easy. 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, we can’t use the cut macro to look for a comment line, but this:

    \def\lst@CommentLine{%
        \expandafter\lst@TestCL\lst@line//\relax}

Additional ’//’ and ’\relax’ hold up the syntax of the cut macro. That’s the point. We use an \expandafter, because we need the content of \lst@line and not the macro token itself as parameter. So the test macro is called (or expanded) after the content is written behind.

\lst@TestCL Why we don’t use the cut macro here? Our additional ’//’ would be added to the comment! Therefore:

    \def\lst@TestCL#1//#2\relax{%
        \ifx\empty#2\empty %
            \let\lst@commentline\empty %
        \else %
            \expandafter\lst@CutCL\lst@line\relax %
        \fi}

If you compare the definition of \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.

\DeclareCommentLine \lst@CommentLine \lst@TestCL \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 \DeclareCommentLine is 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 nth parameter of a macro within a macro is ##n. If you know this, following is clear: It’s the same as the simplified example.

15 \def\DeclareCommentLine#1\relax{%
16 \ifx\@empty#1\@empty \let\lst@CommentLine\@empty %
17 \else
18  \def\lst@CommentLine{\expandafter\lst@TestCL\lst@line#1\relax}%
19  \def\lst@TestCL##1#1##2\relax{%
20  \ifx\@empty##2\@empty \let\lst@commentline\@empty %
21  \else \expandafter\lst@CutCL\lst@line\relax %
22  \fi}%
23  \def\lst@CutCL##1#1##2\relax{%
24  \def\lst@line{##1}\def\lst@commentline{#1##2}}%
25 \fi}

\lst@DefineSingleComment \lst@SOC \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 switched by the cut macros. The last two parameters of lst@DefineSingleComment are the character sequences for the beginning and ending of a single comment, of course. The first parameter is used as suffix for the macro names.

26 \def\lst@DefineSingleComment[#1]#2 #3\relax{%
27 \ifx\@empty#3\@empty %
28  \expandafter\let\csname lst@SOC#1\endcsname\relax %
29  \expandafter\let\csname lst@EOC#1\endcsname\relax %
30 \else %
31  \expandafter\def\csname lst@SOC#1\endcsname{\expandafter %
32  \expandafter\csname lst@TestSOC#1\endcsname \lst@line#2\relax}%
33  \expandafter\def\csname lst@TestSOC#1\endcsname##1#2##2\relax{%
34  \ifx\@empty##2\@empty\else \expandafter %
35  \expandafter\csname lst@CutSOC#1\endcsname \lst@line\relax %
36  \fi}%
37  \expandafter\def\csname lst@CutSOC#1\endcsname##1#2##2\relax{%
38  \lst@commenttrue \def\lst@line{##1}\def\lst@comment{#2##2}}%
39  \expandafter\def\csname lst@EOC#1\endcsname{\expandafter %
40  \expandafter\csname lst@TestEOC#1\endcsname \lst@line#3\relax}%
41  \expandafter\def\csname lst@TestEOC#1\endcsname ##1#3##2\relax{%
42  \ifx\@empty##2\@empty %

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.

43  \let\lst@comment\lst@line \let\lst@line\@empty %
44  \else \expandafter %
45  \expandafter\csname lst@CutEOC#1\endcsname\lst@line\relax%
46  \fi}%
47  \expandafter\def\csname lst@CutEOC#1\endcsname##1#3##2\relax{%
48  \lst@commentfalse \def\lst@line{##2}\def\lst@comment{##1#3}}%
49 \fi}

\DeclareSingleComment That’s an abbreviation of the macro just defined, but where the suffix-parameter is empty.

50 \def\DeclareSingleComment{\lst@DefineSingleComment[]}

\DeclarePairedComment First we define a single comment. Then we adjust one cut macro: The SOC delimiter is defined to belong to the line and not to the comment.

51 \def\DeclarePairedComment#1\relax{%
52  \lst@DefineSingleComment[]#1 #1\relax %
53  \def\lst@CutSOC##1#1##2\relax{%
54  \lst@commenttrue \def\lst@line{##1#1}\def\lst@comment{##2}}}%

\DeclareDoubleComment We define a single comment and another one with slightly different names (additional @). Then we compose the two single comments.

55 \def\DeclareDoubleComment#1 #2 #3 #4\relax{%
56  \lst@DefineSingleComment[]#1 #2\relax %
57  \lst@DefineSingleComment[@]#3 #4\relax %
58  \lst@HookComment#1 #3 \lst@TestSOC@\lst@EOC@\lst@SavedEOC}%

\lst@HookComment The purpose of this macro is to compose a SOC/EOC pair already defined with another SOC/EOC pair, which need not to be defined yet. 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. The first and second parameter are the SOC delimiters of the first (defined) and second SOC/EOC pair, respectively. Therefor they are separated by blank spaces. The third and fourth parameters are the TestSOC and EOC macros of the second SOC/EOC pair. Parameter five is a macro name used to save a EOC macro. That’s done in the second line:

59 \def\lst@HookComment#1 #2 #3#4#5{%
60  \let#5\lst@EOC %
61  \def\lst@TestSOC##1#1##2\relax{%

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 \lst@EOC be the macro, which looks for the end of that comment.

62  #3##1#2\relax %
63  \lst@ifcomment \let\lst@EOC#4%

Otherwise we do the test for this comment. If there is a comment, we cut up the line and let \lst@EOC be the macro, which looks for the end of this comment.

64  \else %
65  \ifx\@empty##2\@empty \else %
66  \expandafter\lst@CutSOC\lst@line\relax %
67  \let\lst@EOC#5%
68  \fi %
69  \fi}}

\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.

70 \def\DeclareNestedComment#1 #2\relax{%
71  \lst@DefineSingleComment[]#1 #2\relax %
72  \def\lst@TestEOC##1#2##2\relax{%

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.

73  \lst@CountSOC##1#1\relax %
74  \ifx\@empty##2\@empty %
75  \let\lst@comment\lst@line \let\lst@line\@empty %
76  \else %
77  \expandafter\lst@CutEOC\lst@line\relax %
78  \fi}%

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.

79  \def\lst@CutEOC##1#2##2\relax{%
80  \advance\lst@commentdepth by -1\relax %
81  \ifnum 0=\lst@commentdepth \lst@commentfalse\fi %
82  \def\lst@line{##2}\def\lst@comment{##1#2}}%

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.

83  \def\lst@CountSOC##1#1##2\relax{%
84  \ifx\@empty##2\@empty\else %
85  \advance\lst@commentdepth by 1%
86  \def\@tempa{\lst@CountSOC##2\relax}%

Note: \@tempa is executed after the closing \fi to call the macro again.

87  \expandafter\@tempa %
88  \fi}}
\DeclareCLPercent This command is equivalent to \DeclareCommentLine %\relax, where the per-

cent has the catcode we need when we input a listing.

89 {\catcode`\%=12 \gdef\DeclareCLPercent{\DeclareCommentLine %\relax}}

\DeclareDoubleCommentPascal Dito for Pascal comments.
90 \begingroup \catcode`\[=1 \catcode`\]=2
91 \catcode`\{=\active \catcode`\}=\active \catcode`\*=\active
92 \gdef\DeclareDoubleCommentPascal[\DeclareDoubleComment (* *) { }\relax]
93 \endgroup

4.3 Keywords

\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 key is a keyword, we define a macro

    \def\lst@test#1,key,#2\relax{...}

Afterwards we call the macro with the parameters

all current keywords,key,\relax

When TEX passes the arguments, the second parameter is empty, if and only if key is not a current keyword. So we are able to decide whether to make a normal box, or a box with keywordstyle.

94 \def\lst@CaseSensitiveKeywords#1\relax{%
95  \def\lst@test##1,#1,##2\relax{%
96  \ifx \@empty##2\@empty \lst@MakeBox{}%
97  \else \lst@MakeBox{\lst@keywordstyle}%
98  \fi}%

We only need to call the macro defined right before. ,#1,\relax holds up the syntax of the macro.

99  \expandafter\lst@test\lst@keywords,#1,\relax}%

Since TEX always passes two arguments to the test macro, TEX splits the whole ’input’ \lst@keywords,#1,\relax in two parts. So there is no need to sort the keywords by probability.^{4}

\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 upper case.

100 \def\lst@NonCaseSensitiveKeywords#1\relax{%
101  \uppercase{\def\lst@test##1,#1,##2\relax{%
102  \ifx \@empty##2\@empty \lst@MakeBox{}%
103  \else \lst@MakeBox{\lst@keywordstyle}%
104  \fi}}%
105  \expandafter\uppercase\expandafter{%
106  \expandafter\lst@test\lst@keywords,#1,\relax}}%

4If you sort the keywords by probability and make a loop for the keyword tests, which terminates right after finding a keyword, you might think that’s faster than the TEXnique used here. Well, if your source code uses the three or four most common keywords only, you are right.

Most cases it will be slow. In fact the versions 0.1 and 0.11 have used something like loops, even something faster, but which is much slower than this here.

\lst@IfOneOf \lst@ifoneof We define two macros, which are very familiar with the keyword tests. The first macro is a case sensitive version of the second one. The first parameter is terminated by \relax, the other three are not. If the first parameter is found in the second parameter (a keyword list) the third parameter is executed. Otherwise we perform the forth. The implementation is clear.

107 \def\lst@IfOneOf#1\relax#2{%
108  \def\lst@test##1,#1,##2\relax{%
109  \ifx \@empty##2\@empty \expandafter\@secondoftwo %
110  \else \expandafter\@firstoftwo %
111  \fi}%
112  \lst@test,#2,#1,\relax}%
113 \def\lst@ifoneof#1\relax#2{%
114  \uppercase{\def\lst@test##1,#1,##2\relax{%
115  \ifx \@empty##2\@empty \expandafter\@secondoftwo %
116  \else \expandafter\@firstoftwo %
117  \fi}}%
118  \uppercase{\lst@test,#2,#1,\relax}}%

4.4 Commands

\selectlisting 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.

119 \newcommand\selectlisting[2][]{%
120  \@ifundefined{lstdrv@#2@}{\input{lst#2.sty}}{}%
121  \@ifundefined{lstdrv@#2@}{%
122  \PackageError{Listings}{Driver file for `#2' corrupt}{%
123  The driver file doesn't define \string\lstdrv@#2@.}}{%
124  \@ifundefined{lstdrv@#2@#1}{%
125  \PackageError{Listings}{Option `#1' not supported}{%
126  The driver file doesn't define \string\lstdrv@#2@#1.}}{%
127  \csname lstdrv@#2@#1\endcsname \def\lst@curr{#2}\def\lst@opt{#1}}}}

\lst@ifselect \lst@ifoption These two private macros are similar to L^{A}TEX 2ε’s \@ifundefined, except that the selected language and option are tested, of course.

128 \def\lst@ifselect#1{\def\lst@test{#1}%
129  \ifx\lst@curr\lst@test \expandafter\@firstoftwo %
130  \else \expandafter\@secondoftwo \fi}
131 \def\lst@ifoption#1{\def\lst@test{#1}%
132  \ifx\lst@opt\lst@test \expandafter\@firstoftwo %
133  \else \expandafter\@secondoftwo \fi}

\keywordstyle \commentstyle \stringstyle \labelstyle The following user commands save the parameter in (private) macros. The labelstyle command checks for a legal step count for labels.

134 \newcommand\keywordstyle[1]{\def\lst@keywordstyle{#1}}
135 \newcommand\commentstyle[1]{\def\lst@commentstyle{#1}}
136 \newcommand\stringstyle[1]{\def\lst@stringstyle{#1}}
137 \newcommand\labelstyle[2][1]{\def\lst@labelstyle{#2}%
138  \ifnum #1>-1 \def\lst@labelstep{#1}\else %

139  \PackageError{Listings}{Nonnegative integer expected}{%
140  You can't use `#1' as step count for labels.^^J%
141  I'll forget it and proceed.}\fi}
\tablength \lstbaseem \lstlineskip  \tablength and \lstbaseem also look, if the arguments are legal.
142 \newcommand\tablength[1]{\ifnum#1>0 \def\lst@tablength{#1}\else %
143  \PackageError{Listings}{Strict positive integer expected}{%
144  You can't use `#1' as tablength.^^J I'll forget it and proceed.}\fi}
145 \newcommand\lstbaseem[1]{\ifdim #1em>0pt \def\lst@baseem{#1}\else %
146  \PackageError{Listings}{Strict positive number expected}{%
147  You can't use `#1' as baseem.^^J I'll forget it and proceed.}\fi}
148 \newcommand\lstlineskip[1]{\def\lst@lineskip{#1}}
\prelisting \postlisting \spreadlisting \keywords \morekeywords \stringizer More ’parameter-saving’ commands:
149 \newcommand\prelisting[1]{\def\lst@prelisting{#1}}
150 \newcommand\postlisting[1]{\def\lst@postlisting{#1}}
151 \newcommand\spreadlisting[1]{\lst@halfspread#1\relax %
152  \lst@halfspread 0.5\lst@halfspread\relax}
153 \newcommand\keywords[1]{%
154  \edef\lst@keywords{,\zap@space#1 \@empty}}
155 \newcommand\morekeywords[1]{%
156  \edef\lst@keywords{\lst@keywords,\zap@space#1 \@empty}}
157 \newcommand\stringizer[2][d]{%
158  \@ifundefined{lst@#1TestStringizer}{%
159  \PackageError{Listings}{Illegal stringizer option `#1'}{%
160  Available options are 'b' and 'd'.}}{%
161  \expandafter\let\expandafter\lst@TestStringizer %
162  \csname lst@#1TestStringizer\endcsname \def\lst@stringizer{#2}}}
\blankstringtrue \blankstringfalse \sensitivetrue \sensitivefalse The user switches assign the right macros.
163 \newcommand\blankstringtrue{%
164  \let\lst@MakeStringBox\lst@MakeBox}
165 \newcommand\blankstringfalse{%
166  \let\lst@MakeStringBox\lst@MakeSpecialStringBox}
167 \newcommand\sensitivetrue{%
168  \let\lst@KeywordOrNot\lst@CaseSensitiveKeywords}
169 \newcommand\sensitivefalse{%
170  \let\lst@KeywordOrNot\lst@NonCaseSensitiveKeywords}

\normallisting The default style is set using the previous commands:

171 \newcommand\normallisting{%
172  \keywordstyle{\bfseries}\commentstyle{\itshape}%
173  \stringstyle{}\labelstyle[0]{}%
174  \prelisting{}\postlisting{}%
175  \spreadlisting{0pt}\blankstringfalse}

\listoflistings At the end of this section we define commands for the list of listings. It’s a

 derivation of \listoffigures.
176 \newcommand\listoflistings{%

177  \ifx\chapter\undefined %
178  \expandafter\section \else \expandafter\chapter %
179  \fi *{\listlistingsname %
180  \@mkboth{\MakeUppercase\listlistingsname}%
181  {\MakeUppercase\listlistingsname}}%
182  \@starttoc{lol}}
183 \newcommand\listlistingsname{Listings}

\lst@ListOfListingsEntry And at the very end a command to add an entry to the list. The first parameter is the name of the listing, and the second is reserved for the line range, I think, but not used so far.

184 \newcommand\lst@ListOfListingsEntry[2]{%
185  \ifx \@empty#1\@empty \else %
186  \addtocontents{lol}{\protect\ListOfListingsLine{#1}{#2}%
187  {\lst@curr}{\thepage}}%
188  \fi}
189 \newcommand\ListOfListingsLine[4]{%
190  \@dottedtocline{1}{1.5em}{2.3em}{#1}{#4}}

4.5 Typesetting a listing

\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 process the listing. But all this only happens, if listings are desired.

191 \newcommand\inputlisting[2][1,999999]{%
192  \lst@ListOfListingsEntry{#2}{}%
193  \iflisting %
194  \batchmode \openin\lst@inputfile#2 \errorstopmode %
195  \ifeof\lst@inputfile %
196  \PackageError{Listings}{File `#2' not found}{%
197  You must tell me the right name or I can't do the job.}%
198  \else %
199  \message{(#2}\lst@ProcessListing[#1]\message{)}%
200  \fi \closein\lst@inputfile %
201  \else %
202  \begin{center}%
203  --- Listing of #2 has been skipped. ---
204  \end{center}%
205  \fi}

\lst@ProcessListing The two parameters of this command are the first and last output line, respectively. First we set up a bit and skip the lines of the listing upto the first printing line.

206 \def\lst@ProcessListing[#1,#2]{%
207  \lst@Begin{#1}%
208  \lst@lastno #2%
209  \@whilenum #1>\lst@lineno \do %
210  {\read\lst@inputfile to\lst@line %
211  \advance\lst@lineno\@ne}%

The following loop terminates, if the end of file or the specified last line is reached. In the loop we read and process the listing line by line.

212  \lst@endinputfalse %
213  \loop %
214  \read\lst@inputfile to\lst@line %
215  \ifeof\lst@inputfile \lst@endinputtrue \fi %
216  \ifnum\lst@lastno<\lst@lineno\lst@endinputtrue\fi %
217  \lst@ifendinput\else %
218  \expandafter\lst@RemovePar\lst@line\par\relax %
219  \lst@AllLineProcessing %
220  \repeat %
221  \lst@End}

\lst@RemovePar The next macro removes (together with the special call above) a \par from the input line. So we need only one \long definition, namely this here.

222 \long\def\lst@RemovePar#1\par#2\relax{\def\lst@line{#1}}

\listing Now we define the environment for typesetting listings. To read the TEX-file line by line we have to make the end of line character ^^M active. If no output is desired, we typeset a message and read the listing without doing any output. Ending the environment is very easy.

223 \newenvironment{listing}{%
224  \iflisting\else
225  \begin{center}%
226  --- Listing has been skipped. ---
227  \end{center}%
228  \fi %
229  \lst@Begin{1}\catcode`\^^M=\active %
230  \lstenv@SkipLineAndProcess}{}

\lstenv@SkipLineAndProcess We will use a mechanism used in the new implementation of L^{A}TEX’s verbatim environments. I don’t explain it here. It is described in section 3.4 of [17].

231 \begingroup
232 \catcode`\!=\active \catcode`\(=\active \catcode`\)=\active
233 \lccode`\!=`\\ \lccode`\(=`\{ \lccode`\)=`\}
234 \catcode`\~=\active \lccode`\~=`\^^M
235 \lowercase{

The effect of \lowercase is that all !, (, ) and ~ of the argument are converted

to \, {, } and ^^M. The macro \lstenv@SkipLineAndProcess skips the rest of

the line, tests the optional argument and begins the loop of processing.

236 \gdef\lstenv@SkipLineAndProcess#1~{%
237  \lstenv@TestOptional#1[]~\lstenv@ReadAndProcess}

\lstenv@TestOptional The second parameter is empty, if and only if there is no optional argument.

238 \gdef\lstenv@TestOptional#1[#2]#3~{%
239  \ifx\@empty#2\@empty\else \lst@ListOfListingsEntry{#2}{}\fi}

\lstenv@ReadAndProcess The macro \lstenv@ReadAndProcess gets the input upto the next end of

line character. We append \end{listing}\relax to hold up the syntax of

\lstenv@Process.
240 \gdef\lstenv@ReadAndProcess#1~{\lstenv@Process#1!end(listing)\relax}

\lstenv@Process 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 the right macro to be done next.

241 \gdef\lstenv@Process#1!end(listing)#2\relax{%
242  \ifx \@empty#2\@empty %
243  \iflisting \def\lst@line{#1}\lst@AllLineProcessing \fi %
244  \let\lst@next\lstenv@ReadAndProcess %
245  \else %
246  \def\lst@next{\lst@End\end{listing}}%
247  \fi \lst@next}
248 }\endgroup

\lst@Begin \lst@End Let’s look what’s to do to begin and end a listing, respectively. We insert a small skip, the user defined \lst@prelisting and \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.

249 \newcommand\lst@Begin[1]{%
250  \smallbreak\bgroup\lst@prelisting %
251  \parskip\lst@lineskip %
252  \lst@stringfalse \lst@commentdepth0 \lst@commentfalse %
253  \let\lst@comment\@empty \let\lst@commentline\@empty %
254  \lst@lineno\@ne %

The following two lines ensure, that TEX doesn’t read font information from other files when catcodes are changed.

255  \setbox0\hbox{{\lst@keywordstyle}{\lst@commentstyle}%
256  {\lst@stringstyle}{{\lst@labelstyle0}}}%

The textwidth for a listing is spread using a parshape command every paragraph. If \lst@labelstep is zero, no labels (=line numbers) are printed.

257  \@tempdima\textwidth \advance\@tempdima by 2\lst@halfspread %
258  \expandafter\ifnum \lst@labelstep=0 %
259  \everypar{\parshape 1 -\lst@halfspread \@tempdima}%
260  \else %

The parameter is the number of the first printing line. We calculate how many lines it will take to set the first label (a line number) and assign it to \@tempcnta.

261  \@tempcnta#1\divide\@tempcnta\lst@labelstep %
262  \multiply\@tempcnta-\lst@labelstep \advance\@tempcnta#1\relax %
263  \ifnum\@tempcnta>0 \advance\@tempcnta-\lst@labelstep \fi %

Defining \everypar is easy now and some other things also.

264  \everypar{\parshape 1 -\lst@halfspread \@tempdima %
265  \ifnum \@tempcnta=0 %

266  \advance\@tempcnta-\lst@labelstep \llap{%
267  \bgroup\lst@labelstyle\the\lst@lineno\relax\egroup\ }%
268  \fi %
269  \advance\@tempcnta\@ne}%
270  \fi %
271  \expandafter\lst@width\lst@baseem em %
272  \lst@ChangeCatcodes %

Finally we call the language’s own prepare macro.

273  \edef\next{lstdrv@\lst@curr @PrepareListing}%
274  \expandafter\csname\next\endcsname}

The ending of a listing is not very exciting.

275 \def\lst@End{\lst@postlisting\catcode`\%=\lst@ccPercent %
276  \par\removelastskip\egroup \smallbreak\ignorespaces}

4.6 Line processing

\lst@AllLineProcessing Here comes the single line processing. First we collect the line processing in one macro: Some initialization, pre-processing, processing and post-processing, but only if the line is not empty. We increase the current line number also.

277 \def\lst@AllLineProcessing{%
278  \ifx \lst@line\@empty \par\noindent\hbox{}\else
279  \let\lst@text\@empty \lst@length0 \global\lst@pos0 %
280  \let\lst@lastother\@empty %
281  \par\noindent \lst@PrePL \lst@ProcessLine \lst@PostPL %
282  \fi \advance\lst@lineno\@ne}

\lst@PrePLDefault \lst@PostPLDefault Before considering the main macro we define the defaults for \lst@PrePL and \lst@PostPL. The latter gives a warning, if a string exceeds a line.

283 \let\lst@PrePLDefault\relax
284 \def\lst@PostPLDefault{%
285  \lst@ifstring %
286  \PackageWarning{Listings}{string constant exceeds line}%
287  \lst@stringfalse %
288  \fi}

\lst@ProcessLine Now the main macro for line processing. There is no parameter, because the data is given by \lst@line. We construct a loop by defining the macro \next to call this macro again. But this definition might changes soon to terminate line processing.

289 \def\lst@ProcessLine{\let\next\lst@ProcessLine %

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 \lst@comment and might changes the boolean \lst@ifcomment.

290  \lst@ifcomment \lst@EOC %

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 switch to comment mode locally and call the macro.

291  {\lst@commenttrue \expandafter\lst@Tokenize\lst@comment\relax}%

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 \next.

292  \let\lst@comment\@empty \lst@ifcomment \let\next\relax \fi %
293  \else %

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).

294  \lst@SOC \lst@CommentLine %

Now \lst@line has been cut to the noncomment rest. We have to find the keywords. \relax is used as a brake: It marks the end and will terminate tokenizing.

295  {\lst@commentfalse \expandafter\lst@Tokenize\lst@line\relax}%

If a string has begun in \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. To handle this we use two \relax as brake and might redefine \next. \lst@PostPL might gives a warning to the user.

296  \lst@ifstring %
297  \lst@commentfalse %
298  \expandafter\expandafter\expandafter\lst@TypesetChar %
299  \expandafter\lst@commentline\lst@comment\relax\relax %
300  \let\lst@comment\@empty \let\lst@commentline\@empty %
301  \ifx \lst@line\@empty \let\next\relax \fi %
302  \else %

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.

303  \ifx\lst@commentline\@empty \else %
304  \lst@commenttrue %
305  \expandafter\expandafter\expandafter\lst@Tokenize %
306  \expandafter\lst@commentline\lst@comment\relax %
307  \lst@commentfalse %
308  \fi %

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 \lst@line — the implizit parameter of this macro. If there is no comment, we redefine \next.

309  \lst@ifcomment \let\lst@line\lst@comment %
310  \else \let\next\relax %
311  \fi %

We have to close some ifs and do the next thing.

312  \fi %
313  \fi\next}

\lst@TypesetChar The following macro has been used in the last macro. It typesets the next character and removes it from the input line.

314 \def\lst@TypesetChar#1#2\relax{\def\lst@line{#2}\lst@OutputChar#1}

\lst@ProcessWhitespaces This macro processes all whitespaces (blank spaces and tabulators here) from the beginning of \lst@line upto the first non-whitespace. The macro assumes that \lst@text is already output.

315 \def\lst@ProcessWhitespaces{%
316  \expandafter\lst@TestWhitespace\lst@line\relax}

\lst@EndTestWhitespace To end the whitespace test we get the line upto the closing \relax and assign it

to \lst@line.
317 \def\lst@EndTestWhitespace#1\relax{\def\lst@line{#1}}

\lst@TestWhitespace The real work is done here. We test for a whitespace, do the output and decide what’s to be done next.

318 \def\lst@TestWhitespace#1{\let\next\lst@TestWhitespace %
319  \ifcat #1&\lst@GotoNextTabStop %
320  \else \if #1\lst@outputblank \lst@OutputChar#1%
321  \else
322  \ifx#1\relax \let\lst@line\@empty \let\next\relax %
323  \else \def\next{\lst@EndTestWhitespace#1}%
324  \fi %
325  \fi \fi \next}

The line processing is complete. Now we will try to scan keywords.

4.7 Tokenizing

We define two tokenize macros. The first determines potential keywords by collecting characters upto a nonletter. After outputting the potential keyword the second macro is called to gather all characters upto the next letter. Then these characters are output and the first macro is called again. That’s how the two macros work together.

\lst@Tokenize The tokenize macro gets code upto \relax and scans for keywords and strings. In fact it only cuts up potential keywords, which are tested right before their output. We define the next operation first:

326 \def\lst@Tokenize#1{\let\lst@next\lst@Tokenize%

An incoming letter is gathered. If we found a nonletter, we output the preceding text. The keyword test takes place there.

327  \ifcat #1a%
328  \edef\lst@text{\lst@text#1}\advance\lst@length\@ne %
329  \else %
330  \lst@Output %

If the other character is a tabulator, we go to the next tab stop.

331  \ifcat #1&\lst@GotoNextTabStop %
332  \else %

Getting to the terminator \relax ends tokenizing by defining next operation empty, here \relax. Otherwise our next operation is ’tokenizing’ nonletter characters.

333  \ifx#1\relax \let\lst@next\relax %
334  \else \let\lst@next\lst@TokenizeOther %

If we are in comment mode, we have not to look for strings and gather the nonletter character. Otherwise we look for stringizer. Then come some closing \fis and the next operation.

335  \lst@ifcomment \lst@length\z@ \lst@AppendOther#1%
336  \else \lst@TestStringizer#1\fi %
337  \fi %
338  \fi \fi \lst@next}

\lst@TokenizeOther This macro looks like lst@Tokenize except that we have to insert some

\lst@OutputOther.
339 \def\lst@TokenizeOther#1{%
340  \let\lst@next\lst@TokenizeOther %
341  \ifcat #1a%
342  \lst@OutputOther \let\lst@lastother\@empty %
343  \def\lst@text{#1}\lst@length\@ne %
344  \let\lst@next\lst@Tokenize %
345  \else \ifcat #1&%
346  \lst@OutputOther \lst@GotoNextTabStop %
347  \else %
348  \ifx#1\relax \lst@OutputOther \let\lst@next\relax %

Now comes something new. If we find two successive blank spaces, we output all preceding other characters first. This avoid alignment problems when too many blanks follow each other. The rest is unchanged.

349  \else \ifx\lst@lastother\lst@inputblank\if#1\lst@inputblank %
350  \lst@OutputOther \fi\fi %
351  \lst@ifcomment \lst@AppendOther#1%
352  \else \lst@TestStringizer#1%
353  \fi \fi %
354  \fi \fi \lst@next}

\lst@AppendOther This macro simply appends a character to the token register \lst@other.

355 \def\lst@AppendOther#1{\advance\lst@length\@ne %
356  \expandafter\lst@other\expandafter{\the\lst@other#1}}

\lst@bTestStringizer Here we do the stringizer tests. If a string already started, we gather the current character and look for the closing stringizer. If we’ve found it, we output \lst@other and switch the string boolean, but only if the preceding other character is not a backslash (which inserts a stringizer at the current position of the string).

357 \def\lst@bTestStringizer#1{%
358  \lst@ifstring \lst@AppendOther#1%
359  \expandafter\ifx\lst@closing@stringizer#1%
360  \ifx\lst@lastother\lst@inputbackslash \else %
361  \lst@OutputOther \global\lst@stringfalse %
362  \fi \fi %
363  \def\lst@lastother{#1}%

If we are not in string mode, we compare the current character with all given stringizers and gather the character afterwards, since the string boolean might changes and we might output the preceding characters with a different style.

364  \else %
365  \def\lst@lastother{#1}%
366  \expandafter\lst@DoStringizerTest\lst@stringizer\relax %
367  \lst@AppendOther#1%
368  \fi}
\lst@dTestStringizer Nearly the same:
369 \def\lst@dTestStringizer#1{\def\lst@lastother{#1}%
370  \lst@ifstring \lst@AppendOther#1%
371  \ifx\lst@closing@stringizer\lst@lastother %
372  \lst@OutputOther \global\lst@stringfalse %
373  \fi %
374  \else %
375  \expandafter\lst@DoStringizerTest\lst@stringizer\relax %
376  \lst@AppendOther#1%
377  \fi}

\lst@DoStringizerTest Now we consider a stringizer test. Reaching \relax results in doing nothing and so terminating the tests.

378 \def\lst@DoStringizerTest#1{%
379  \ifx#1\relax \else %

Otherwise we compare the current character and the current stringizer. If they are equal, we output the preceding characters, switch the string boolean and save the stringizer as closing stringizer.

380  \expandafter\ifx\lst@lastother#1\relax %
381  \lst@OutputOther \global\lst@stringtrue %
382  \gdef\lst@closing@stringizer{#1}%
383  \fi %

At the end we call this macro again. The macro terminates reaching the \relax!

384  \expandafter\lst@DoStringizerTest %
385  \fi}%

4.8 Output

\lst@Output It’s time to do text output. First we look, if there is anything to output.

386 \def\lst@Output{%
387  \ifx\lst@text\@empty\else %

Then we decide, whether to make a stringbox (using stringstyle) or a box for a comment (using commentstyle as explicit parameter).

388  \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
389  \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %

If we output neither a string nor a comment, we look for a keyword. The output takes place in the macro \lst@KeywordsOrNot (see section 5). \relax terminates the text parameter.

390  \expandafter\lst@KeywordOrNot\lst@text\relax %
391  \fi \fi %

Finally we hold up the current column, empty the text and close the starting ’if text not empty’.

392  \global\advance\lst@pos by -\lst@length %
393  \let\lst@text\@empty \lst@length0 %
394  \fi}

\lst@OutputOther To output the characters from the token register \lst@other, we assign these characters to a macro. The rest is the same as in \lst@Output, except that we need no keyword tests and make a normal box instead.

395 \def\lst@OutputOther{%
396  \expandafter\def\expandafter\lst@text\expandafter{\the\lst@other}%
397  \ifx\lst@text\@empty\else %
398  \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
399  \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
400  \lst@MakeBox{}%
401  \fi \fi %
402  \global\advance\lst@pos by -\lst@length %
403  \lst@other{}\let\lst@text\@empty \lst@length0 %
404  \fi}

\lst@MakeBox Consider the different boxes now. A box must take \lst@length characters: the width is \lst@length·\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. Again \relax is a brake.

405 \def\lst@MakeBox#1{%
406  \hbox to \lst@length\lst@width{#1\hss %
407  \expandafter\lst@FillBox\lst@text\relax \hss}}

\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 \fi!

408 \begingroup
409 \catcode`\_=11
410 \gdef\lst@FillBox#1{%
411  \ifx\relax#1\else %

412  \ifx#1_\textunderscore \else #1\fi \hss %
413  \expandafter\lst@FillBox %
414  \fi}
415 \endgroup

\lst@MakeSpecialStringBox A stringbox is nearly the same: We only let the ’normal blank’ be ’ ’.

416 \def\lst@MakeSpecialStringBox#1{%
417  \hbox to\lst@length\lst@width{\let\lst@outputblank\textvisiblespace%
418  #1\hss \expandafter\lst@FillBox\lst@text\relax \hss}}

\lst@OutputChar We define one more macro to save time. It outputs a single character. The implementation should be clear.

419 \def\lst@OutputChar#1{\global\advance\lst@pos by -1%
420  \hbox to \lst@width{\hss %
421  \lst@ifstring \def\lst@text{#1}\lst@length\@ne %
422  \lst@MakeStringBox{\lst@stringstyle}%
423  \else \lst@ifcomment \lst@commentstyle#1\hss %
424  \else #1\hss %
425  \fi \fi}}

\lst@GotoNextTabStop At the end of this section we consider tabulators. As seen, each typeset character decrements the counter \lst@pos. To go to the next tabulator stop, we must first determine how many blanks are needed. We simply add \lst@tablength until \lst@pos is strict positive.

426 \def\lst@GotoNextTabStop{%
427  \@whilenum \lst@pos<1 \do %
428  {\global\advance\lst@pos\lst@tablength}%

Now we make a box having the width of \lst@pos characters and set \lst@pos to zero.

429  \hbox to \lst@pos\lst@width{\hss}\lst@pos0}%

4.9 Special characters

Some definitions of special characters:

430 \def\lst@leftbrace{$\{$}
431 \def\lst@rightbrace{$\}$}
432 \def\lst@less{$<$}
433 \def\lst@greater{$>$}
434 \def\lst@verticalbar{$|$}
435 \def\lst@minus{$-$}
436 \def\lst@multiply{$*$}
\lst@MakeDigitsLetter This macro is similar to \makeatletter.
437 \def\lst@MakeDigitsLetter{\catcode`\0=11\catcode`\1=11%
438  \catcode`\2=11\catcode`\3=11\catcode`\4=11\catcode`\5=11%
439  \catcode`\6=11\catcode`\7=11\catcode`\8=11\catcode`\9=11}

\lst@DefineCatcodes At the moment only the catcode of − is language specific. This macro stores such values.

440 \def\lst@DefineCatcodes#1{%
441  \def\lst@ChangeMoreCatcodes{\catcode`\-=#1}}

\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 \, { and } are essential for doing that.

442 \begingroup
443 \catcode `/=0       \catcode `(= 1      \catcode `)=2 % new \, { and }
444 \catcode`\<=\active \catcode`\>=\active \catcode`\|=\active
445 \catcode`\-=\active \catcode`\*=\active
446 \catcode`\{=\active \catcode`\}=\active \catcode`\\=\active

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.

447 /gdef/lst@inputbackslash(\)%
448 /catcode`/ =/active%
449 /gdef/lst@inputblank( )%
450 /gdef/lst@outputblank(/ )%

The following macro changes catcodes and the definition of active characters at the time we input a listing.

451 /gdef/lst@ChangeCatcodes(%
452 /catcode`/ =/active/def (/lst@outputblank)%
453 /catcode`/\=/active/def\($/backslash$)%
454 /catcode`/{=/active/def{(/lst@leftbrace)%
455 /catcode`/}=/active/def}(/lst@rightbrace)%
456 /catcode`/<=/active/def<(/lst@less)%
457 /catcode`/>=/active/def>(/lst@greater)%
458 /catcode`/|=/active/def|(/lst@verticalbar)%
459 /catcode`/-=/active/def-(/lst@minus)%
460 /catcode`/*=/active/def*(/lst@multiply)%
461 /chardef~="7E%

A tabulator (ASCII code 9=ord(I)−64) gets the catcode of a TEX-tabulator.

462 /catcode`/^^I=4%

Some characters are treated as other characters (12) or as letters (11).

463 /catcode`/$=11/catcode`/_=11/lst@MakeDigitsLetter%
464 /catcode`/&=12/catcode`/^=12/catcode`/"=12/catcode`/#=12%
465 /chardef/lst@ccPercent=/catcode`/%/catcode`/%=12% save catcode
466 /lst@ChangeMoreCatcodes/makeatletter)%
467 /endgroup

All changed catcodes (time of definition) are restored by ending the group.

4.10 Initialization

Defaults are selected and the options are processed.

468 \normallisting
469 \listingtrue
470 \tablength{4}
471 \lstlineskip{0pt}
472 \selectlisting{blank}
473 \ProcessOptions

474 ⟨/package⟩

5 Language driver files

Each driver file contains language specific data:

• keywords,

• whether the language is case sensitive or not,

• information about comment lines and other comments,

• the stringizer,

• baseem — the width of a single character box,

• the catcode of the minus −,

• \lst@PrePL and \lst@PostPL are executed before and after the real line processing takes place: \lst@PrePL is intend to manipulate the input, e.g. Fortran uses it to detect comment lines beginning with ’∗’ or ’C’ and Eiffel’s string concatenate mechanism is done there, and e.g. \lst@PostPL might gives a warning, if a string exceeds a line.

The package selects a language by calling \lstdrv@#1@, where #1 is replaced by the language. Additionally the language option (empty or not) is used as suffix, e.g. \lstdrv@cobol@1974. That macro must support the described things.

Some driver files use own data. To setup things like that the macro \lstdrv@#1@PrepareListing is called after all init of the kernel is done (changing catcodes, e.g.). Here #1 is replaced by the language again. If no special setup is needed, a driver file need not to define that macro.

The implemented languages follow as examples. ’???’ in driver files indicate things I don’t know.

5.1 Blank listing

\lstdrv@blank@ For a blank listing we let all empty. \makeatletter lets @ be a letter here. Otherwise we can’t access \lstdrv@blank@.

475 ⟨∗blank⟩

476 \begingroup \makeatletter %

477 \gdef\lstdrv@blank@{%
478  \keywords{}%
479  \sensitivetrue %
480  \DeclareCommentLine\relax %
481  \DeclareSingleComment stuff \relax %
482  \stringizer{}\lstbaseem{0.6}%
483  \lst@DefineCatcodes{\active}%
484  \let\lst@PrePL \lst@PrePLDefault %
485  \let\lst@PostPL\lst@PostPLDefault}%
486 \endgroup %

487 ⟨/blank⟩

5.2 Ada

\lstdrv@ada@ Keywords, comments, … The catcode of the double quote is changed for compatibility with german.sty.

488 ⟨∗ada⟩

489 \begingroup \makeatletter %
490 \catcode`\"=12 \catcode`\-=\active %
491 \gdef\lstdrv@ada@{%
492  \keywords{abort,abs,accept,access,all,and,array,at,begin,body,%
493  case,constant,declare,delay,delta,digits,do,else,elsif,end,%
494  entry,exception,exit,for,function,generic,goto,if,in,is,%
495  limited,loop,mod,new,not,null,of,or,others,out,package,pragma,%
496  private,procedure,raise,range,record,rem,renames,return,%
497  reverse,select,separate,subtype,task,terminate,then,type,%
498  use,when,while,with,xor}%
499  \sensitivefalse %
500  \DeclareCommentLine --\relax %
501  \DeclareSingleComment stuff \relax %
502  \stringizer[d]{"'}\lstbaseem{0.6}% ??? stringizer doubled
503  \lst@DefineCatcodes{\active}%
504  \let\lst@PrePL \lst@PrePLDefault %
505  \let\lst@PostPL\lst@PostPLDefault}%
506 \endgroup %

507 ⟨/ada⟩

5.3 Algol

\lstdrv@algol@ The main driver macro.

508 ⟨∗algol⟩

509 \begingroup \makeatletter %
510 \catcode`\#=12 %
511 \gdef\lstdrv@algol@{% ??? should 'i' be a keyword
512  \keywords{abs,and,arg,begin,bin,bits,bool,by,bytes,case,channel,%
513  char,co,comment,compl,conj,divab,do,down,elem,elif,else,empty,%
514  end,entier,eq,esac,exit,false,fi,file,flex,for,format,from,%
515  ge,goto,gt,heap,if,im,in,int,is,isnt,le,leng,level,loc,long,%
516  lt,lwb,minusab,mod,modab,mode,ne,nil,not,od,odd,of,op,or,ouse,%

517  out,over,overab,par,plusab,plusto,pr,pragmat,prio,proc,re,real,%
518  ref,repr,round,sema,shl,short,shorten,shr,sign,skip,string,%
519  structthen,timesab,to,true,union,up,upb,void,while}%
520  \sensitivefalse % ???
521  \DeclareCommentLine\relax %
522  \DeclarePairedComment #\relax %
523  \stringizer{}\lstbaseem{0.6}%
524  \lst@DefineCatcodes{\active}%
525  \let\lst@PrePL \lst@PrePLDefault %
526  \let\lst@PostPL\lst@PostPLDefault}%
\lstdrv@algol@68 \lstdrv@algol@60 Macros for the optional argument:
527 \global\@namedef{lstdrv@algol@68}{\lstdrv@algol@}%
528 \global\@namedef{lstdrv@algol@60}{\lstdrv@algol@ %
529  \keywords{array,begin,Boolean,code,comment,div,do,else,end,false,%
530  for,goto,if,integer,label,own,power,procedure,real,step,string,%
531  switch,then,true,until,value,while}%
532  \DeclareSingleComment stuff \relax}%
533 \endgroup %

\lstdrv@algol@PrepareListing To implement comments beginning with comment or co we must go deep inside this package again. We need an additional ’ifcomment’ and define Algol’s Prepare-Listing to override the default output macros.

534 \begingroup \makeatletter %
535 \gdef\lstdrv@algol@commenttrue{%
536  \global\let\lstdrv@algol@ifcomment\iftrue}%
537 \gdef\lstdrv@algol@commentfalse{%
538  \global\let\lstdrv@algol@ifcomment\iffalse %
539  \global\let\lstdrv@algol@closingcomment\@empty}%
540 \gdef\lstdrv@algol@PrepareListing{%
541  \lstdrv@algol@commentfalse %
542  \let\lst@OutputOther\lstdrv@algol@OutputOther %
543  \lst@ifoption{60}{\let\lst@Output\lstdrv@algol@Output@ %
544  \let\lst@AppendOther\lstdrv@algol@AppendOther}%
545  {\let\lst@Output\lstdrv@algol@Output}}%

\lstdrv@algol@OutputOther This macro is a simple derivation of \lst@OutputOther. The only difference is that we test Algol’s additional ’ifcomment’ (4th line).

546 \gdef\lstdrv@algol@OutputOther{%
547  \expandafter\def\expandafter\lst@text\expandafter{\the\lst@other}%
548  \ifx\lst@text\@empty\else %
549  \lstdrv@algol@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
550  \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
551  \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
552  \lst@MakeBox{}%
553  \fi \fi \fi %
554  \global\advance\lst@pos by -\lst@length %
555  \lst@other{}\let\lst@text\@empty \lst@length0 %
556  \fi}%

\lstdrv@algol@Output Here we also install an additional ’ifcomment’. If we are in comment mode, we look whether the comment is over or not.

557 \gdef\lstdrv@algol@Output{%
558  \ifx\lst@text\@empty\else %
559  \lstdrv@algol@ifcomment %
560  \ifx\lst@text\lstdrv@algol@closingcomment %
561  \lstdrv@algol@commentfalse %
562  \lst@MakeBox{\lst@keywordstyle}%
563  \else \lst@MakeBox{\lst@commentstyle}%
564  \fi \else %

The next three lines are unchanged.

565  \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
566  \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
567  \expandafter\lst@KeywordOrNot\lst@text\relax %

After the keyword (or non-keyword) is output, we look if a comment starts: If the current text equals co or comment, we enter comment mode and set the closing comment delimiter.

568  \expandafter\lst@ifoneof\lst@text\relax{comment,co}%
569  {\global\let\lstdrv@algol@closingcomment\lst@text}{}%

The rest is unchanged.

570  \fi \fi \fi %
571  \global\advance\lst@pos by -\lst@length %
572  \let\lst@text\@empty \lst@length0 %
573  \fi}%

\lstdrv@algol@Output@ Now we come to Algol 60. First comes the same as above. But: An empty ’closingcomment’ indicates that no end and no else closes a comment, i.e. we look first whether ’end of comment’ tests are legal or not.

574 \gdef\lstdrv@algol@Output@{%
575  \ifx\lst@text\@empty\else %
576  \lstdrv@algol@ifcomment %
577  \ifx\@empty\lstdrv@algol@closingcomment %
578  \lst@MakeBox{\lst@commentstyle}%
579  \else %
580  \expandafter\lst@ifoneof\lst@text\relax{else,end}%
581  {\lstdrv@algol@commentfalse %
582  \lst@MakeBox{\lst@keywordstyle}}%
583  {\lst@MakeBox{\lst@commentstyle}}%
584  \fi \else %

The next three lines are unchanged.

585  \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
586  \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
587  \expandafter\lst@KeywordOrNot\lst@text\relax %

After the keyword (or non-keyword) is output, we look if a comment starts: If the current text equals comment, we enter the comment mode and let \lstdrv@algol@closingcomment empty; if the text equals end, we let ’closingcomment’ not empty, i.e. the comment may closes with else or end (see above).

588  \expandafter\lst@ifoneof\lst@text\relax{comment,end}%
589  {\lstdrv@simula@commenttrue %
590  \expandafter\lst@ifoneof\lst@text\relax{end}%
591  {\gdef\lstdrv@simula@closingcomment{a}}{}}%
592  {}% empty else from 'ifoneof'

The rest is unchanged.

593  \fi \fi \fi %
594  \global\advance\lst@pos by -\lst@length %
595  \let\lst@text\@empty \lst@length0 %
596  \fi}%

\lstdrv@algol@AppendOther@ A semicolon also ends a comment. Hence:

597 \gdef\lstdrv@algol@AppendOther#1{%
598  \lstdrv@algol@ifcomment \if;#1%
599  \lst@OutputOther \lstdrv@algol@commentfalse %
600  \fi \fi %
601  \advance\lst@length\@ne %
602  \expandafter\lst@other\expandafter{\the\lst@other#1}}%
603 \endgroup %

604 ⟨/algol⟩

5.4 C

\lstdrv@c@ Since ∗ will be an active character when we input a listing, we have to change the catcode here.

605 ⟨∗c⟩

606 \begingroup \makeatletter %
607 \catcode`\"=12 \catcode`\*=\active %
608 \gdef\lstdrv@c@{%
609  \keywords{auto,break,case,char,const,continue,default,do,double,%
610  else,enum,extern,float,for,goto,if,int,long,register,return,%
611  short,signed,sizeof,static,struct,switch,typedef,union,%
612  unsigned,void,volatile,while}%
613  \sensitivetrue %
614  \DeclareCommentLine\relax %
615  \DeclareSingleComment /* */\relax %
616  \stringizer[b]{"}\lstbaseem{0.6}%
617  \lst@DefineCatcodes{\active}%
618  \let\lst@PrePL \lstdrv@c@PrePL %
619  \let\lst@PostPL\lst@PostPLDefault}%
620 \endgroup %
\lstdrv@c@PrePL \lstdrv@c@directives We only test for C compiler directives.
621 \begingroup \makeatletter %
622 \gdef\lstdrv@c@PrePL{%
623  \expandafter\lstdrv@c@TestSharp\lst@line\relax\relax}%

624 \gdef\lstdrv@c@directives{,define,elif,else,endif,error,if,ifdef,%
625  ifndef,line,include,pragma,undef}%

\lstdrv@c@TestSharp To implement C (and C++) directives the catcode of # must be changed from ’parameter symbol for macros’ to ’letter’.

626 \catcode`\&=6 \catcode`\#=12 %
627 \gdef\lstdrv@c@TestSharp&1&2\relax{%
628  \if#&1\def\lst@line{&2}%

If the first character of a line is a sharp, we first output that sharp using the keywordstyle. All compiler directives become the current keywords and we output the line, which gets empty afterwards.

629  {\lst@keywordstyle\lst@OutputChar#}%
630  {\let\lst@keywords\lstdrv@c@directives \lst@ProcessLine}%
631  \let\lst@line\@empty %
632  \fi}%
633 \endgroup %

634 ⟨/c⟩

5.5 C++

\lstdrv@cpp@ Since C++ is an extension of C (from the point of view here), we load the C driver file and use the definition there.

635 ⟨∗cpp⟩

636 \selectlisting{c}%
637 \begingroup \makeatletter %
638 \catcode`\_=11 %
639 \gdef\lstdrv@cpp@{\lstdrv@c@ %
640  \morekeywords{asm,bad_cast,bad_typeid,bool,catch,class,const_cast,%
641  delete,dynamic_cast,false,friend,inline,namespace,new,operator,%
642  private,protected,public,reinterpret_cast,static_cast,template,%
643  this,throw,true,try,type_info,typeid,using,virtual,xalloc,%
644  __multiple_inheritance,__single_inheritance,%
645  __virtual_inheritance}%
646  \DeclareCommentLine //\relax}%
647 \global\let\lstdrv@cpp@ansi \lstdrv@cpp %
648 \gdef\lstdrv@cpp@vc{\lstdrv@cpp %
649  \morekeywords{__asm,__based,__cdecl,__declspec,dllexport,dllimport,%
650  __except,__fastcall,__finally,__inline,__int8,__int16,__int32,%
651  __int64,naked,__stdcall,thread,__try,__leave}}%
652 \endgroup %

653 ⟨/cpp⟩

5.6 Cobol

\lstdrv@cobol@keys \lstdrv@cobol@keys@eightyfive \lstdrv@cobol@keys@ibm The keywords first:

654 ⟨∗cobol⟩

655 \begingroup \makeatletter %
656 \catcode`\-=11 \lst@MakeDigitsLetter %

657 \gdef\lstdrv@cobol@keys{ACCEPT,ACCESS,ADD,ADVANCING,AFTER,ALL,%
658  ALPHABETIC,ALSO,ALTER,ALTERNATE,AND,ARE,AREA,AREAS,ASCENDING,%
659  ASSIGN,AT,AUTHOR,BEFORE,BINARY,BLANK,BLOCK,BOTTOM,BY,CALL,CANCEL,%
660  CD,CF,CH,CHARACTER,CHARACTERS,CLOCK-UNITS,CLOSE,COBOL,CODE,%
661  CODE-SET,COLLATING,COLUMN,COMMA,COMMUNICATION,COMP,COMPUTE,%
662  CONFIGURATION,CONTAINS,CONTROL,CONTROLS,CONVERTING,COPY,CORR,%
663  CORRESPONDING,COUNT,CURRENCY,DATA,DATE,DATE-COMPILED,DATE-WRITTEN,%
664  DAY,DE,DEBUG-CONTENTS,DEGUB-ITEM,DEBUG-LINE,DEBUG-NAME,DEBUG-SUB1,%
665  DEBUG-SUB2,DEBUG-SUB3,DEBUGGING,DECIMAL-POINT,DECLARATIVES,DELETE,%
666  DELIMITED,DELIMITER,DEPENDING,DESCENDING,DESTINATION,DETAIL,%
667  DISABLE,DISPLAY,DIVIDE,DIVISION,DOWN,DUPLICATES,DYNAMIC,EGI,ELSE,%
668  EMI,ENABLE,END,END-OF-PAGE,ENTER,ENVIRONMENT,EOP,EQUAL,ERROR,ESI,%
669  EVERY,EXCEPTION,EXIT,EXTEND,FD,FILE,FILE-CONTROL,FILLER,FINAL,%
670  FIRST,FOOTING,FOR,FROM,GENERATE,GIVING,GO,GREATER,GROUP,HEADING,%
671  HIGH-VALUE,HIGH-VALUES,I-O,I-O-CONTROL,IDENTIFICATION,IF,IN,INDEX,%
672  INDEXED,INDICATE,INITIAL,INITIATE,INPUT,INPUT-OUTPUT,INSPECT,%
673  INSTALLATION,INTO,INVALID,IS,JUST,JUSTIFIED,KEY,LABEL,LAST,LEADING,%
674  LEFT,LENGTH,LESS,LIMIT,LIMITS,LINAGE,LINAGE-COUNTER,LINE,%
675  LINE-COUNTER,LINES,LINKAGE,LOCK,LOW-VALUE,LOW-VALUES,MEMORY,MERGE,%
676  MESSAGE,MODE,MODULES,MOVE,MULTIPLE,MULTIPLY,NATIVE,NEGATIVE,NEXT,%
677  NO,NOT,NUMBER,NUMERIC,OBJECT-COMPUTER,OCCURS,OF,OFF,OMITTED,ON,%
678  OPEN,OPTIONAL,OR,ORGANIZATION,OUTPUT,OVERFLOW,PAGE,PAGE-COUNTER,%
679  PERFORM,PF,PH,PIC,PICTURE,PLUS,POINTER,POSITION,PRINTING,POSITIVE,%
680  PRINTING,PROCEDURE,PROCEDURES,PROCEED,PROGRAM,PROGRAM-ID,QUEUE,%
681  QUOTE,QUOTES,RANDOM,RD,READ,RECEIVE,RECORD,RECORDING,RECORDS,%
682  REDEFINES,REEL,REFERENCES,RELATIVE,RELEASE,REMAINDER,REMOVAL,%
683  RENAMES,REPLACING,REPORT,REPORTING,REPORTS,RERUN,RESERVE,RESET,%
684  RETURN,REVERSED,REWIND,REWRITE,RF,RH,RIGHT,ROUNDED,RUN,SAME,SD,%
685  SEARCH,SECTION,SECURITY,SEGMENT,SEGMENT-LIMIT,SELECT,SEND,SENTENCE,%
686  SEPARATE,SEQUENCE,SEQUENTIAL,SET,SIGN,SIZE,SORT,SORT-MERGE,SOURCE,%
687  SOURCE-COMPUTER,SPACE,SPACES,SPECIAL-NAMES,STANDARD,START,STATUS,%
688  STOP,STRING,SUB-QUEUE-1,SUB-QUEUE-2,SUB-QUEUE-3,SUBTRACT,SUM,%
689  SYMBOLIC,SYNC,SYNCHRONIZED,TABLE,TALLYING,TAPE,TERMINAL,TERMINATE,%
690  TEXT,THAN,THROUGH,THRU,TIME,TIMES,TO,TOP,TRAILING,TYPE,UNIT,%
691  UNSTRING,UNTIL,UP,UPON,USAGE,USE,USING,VALUE,VALUES,VARYING,WHEN,%
692  WITH,WORDS,WORKING-STORAGE,WRITE,ZERO,ZEROES,ZEROS}%
693 \gdef\lstdrv@cobol@keys@eightyfive{ALPHABET,ALPHABETIC-LOWER,%
694  ALPHABETIC-UPPER,ALPHANUMERIC,ALPHANUMERIC-EDITED,ANY,CLASS,COMMON,%
695  CONTENT,CONTINUE,DAY-OF-WEEK,END-ADD,END-CALL,END-COMPUTE,%
696  END-DELETE,END-DIVIDE,END-EVALUATE,END-IF,END-MULTIPLY,END-PERFORM,%
697  END-READ,END-RECEIVE,END-RETURN,END-REWRITE,END-SEARCH,END-START,%
698  END-STRING,END-SUBTRACT,END-UNSTRING,END-WRITE,EVALUATE,EXTERNAL,%
699  FALSE,GLOBAL,INITIALIZE,NUMERIC-EDITED,ORDER,OTHER,PACKED-DECIMAL,%
700  PADDING,PURGE,REFERENCE,RELOAD,REPLACE,STANDARD-1,STANDARD-2,TEST,%
701  THEN,TRUE}%
702 \gdef\lstdrv@cobol@keys@ibm{ADDRESS,BEGINNING,COMP-3,COMP-4,%
703  COMPUTATIONAL,COMPUTATIONAL-3,COMPUTATIONAL-4,DISPLAY-1,EGCS,EJECT,%
704  ENDING,ENTRY,GOBACK,ID,MORE-LABELS,NULL,NULLS,PASSWORD,RECORDING,%
705  RETURN-CODE,SERVICE,SKIP1,SKIP2,SKIP3,SORT-CONTROL,SORT-RETURN,%
706  SUPPRESS,TITLE,WHEN-COMPILED}%

707 \endgroup %

\lstdrv@cobol@ Now the main driver macro:

708 \begingroup \makeatletter %
709 \catcode`\"=12%
710 \gdef\lstdrv@cobol@{%
711  \keywords{\lstdrv@cobol@keys,\lstdrv@cobol@keys@eightyfive}%
712  \sensitivefalse % ???
713  \DeclareCommentLine\relax %
714  \DeclareSingleComment stuff \relax %
715  \stringizer[d]{"}\lstbaseem{0.65}%
716  \lst@DefineCatcodes{11}%
717  \let\lst@PrePL\lstdrv@cobol@PrePL %
718  \let\lst@PostPL\relax}%
\lstdrv@cobol@1985 \lstdrv@cobol@1974 \lstdrv@cobol@ibm And macros for the optional argument:
719 \global\@namedef{lstdrv@cobol@1985}{\lstdrv@cobol@}%
720 \global\@namedef{lstdrv@cobol@1974}{\lstdrv@cobol@ %
721  \keywords{\lstdrv@cobol@keys}}%
722 \gdef\lstdrv@cobol@ibm{\lstdrv@cobol@ %
723  \morekeywords{\lstdrv@cobol@keys@ibm}}%
724 \endgroup %
\lstdrv@cobol@PrePL \lstdrv@cobol@TestComment Comments are handled with the \lst@PrePL mechanism. We simply look, if the

seventh character is an asterix (and output the comment if necessary).

725 \begingroup \makeatletter %
726 \gdef\lstdrv@cobol@PrePL{\expandafter\lstdrv@cobol@TestComment %
727  \lst@line\relax\relax\relax\relax\relax\relax\relax\relax}%
728 \catcode`\*=\active %
729 \gdef\lstdrv@cobol@TestComment#1#2#3#4#5#6#7#8\relax{%
730  \ifx #7*%
731  \lst@commenttrue \expandafter\lst@Tokenize\lst@line\relax %
732  \let\lst@line\@empty \lst@commentfalse %
733  \fi}%
734 \endgroup %

735 ⟨/cobol⟩

5.7 Comal 80

\lstdrv@comal@ Only the lonely driver macro.

736 ⟨∗comal⟩

737 \begingroup \makeatletter %
738 \catcode`\"=12 %
739 \gdef\lstdrv@comal@{%
740  \keywords{AND,AUTO,CASE,DATA,DEL,DIM,DIV,DO,ELSE,ENDCASE,ENDIF,%
741  ENDPROC,ENDWHILE,EOD,EXEC,FALSE,FOR,GOTO,IF,INPUT,INT,LIST,%
742  LOAD,MOD,NEW,NEXT,NOT,OF,OR,PRINT,PROC,RANDOM,RENUM,REPEAT,%
743  RND,RUN,SAVE,SELECT,STOP,TAB,THEN,TRUE,UNTIL,WHILE,ZONE}%
744  \sensitivefalse % ???

745  \DeclareCommentLine //\relax %
746  \DeclareSingleComment stuff \relax %
747  \stringizer{"}\lstbaseem{0.65}%
748  \lst@DefineCatcodes{\active}%
749  \let\lst@PrePL \lst@PrePLDefault %
750  \let\lst@PostPL\lst@PostPLDefault}%
751 \endgroup %

752 ⟨/comal⟩

5.8 Eiffel

\lstdrv@eiffel@ The same procedure …

753 ⟨∗eiffel⟩

754 \begingroup \makeatletter %
755 \catcode`\"=12 \catcode`\-=\active %
756 \gdef\lstdrv@eiffel@{%
757  \keywords{alias,all,and,as,BIT,BOOLEAN,CHARACTER,check,class,%
758  creation,Current,debug,deferred,do,DOUBLE,else,elseif,end,%
759  ensure,expanded,export,external,false,feature,from,frozen,if,%
760  implies,indexing,infix,inherit,inspect,INTEGER,invariant,is,%
761  like,local,loop,NONE,not,obsolete,old,once,or,POINTER,prefix,%
762  REAL,redefine,rename,require,rescue,Result,retry,select,%
763  separate,STRING,strip,then,true,undefine,unique,until,variant,%
764  when,xor}%
765  \sensitivetrue %
766  \DeclareCommentLine --\relax %
767  \DeclareSingleComment stuff \relax %
768  \stringizer{"}\lstbaseem{0.6}%
769  \lst@DefineCatcodes{\active}%
770  \let\lst@PrePL \lstdrv@eiffel@PrePL %
771  \let\lst@PostPL\relax}%
772 \endgroup %

Not the same procedure: Since ’%’ continues a string, we need a different comment character and let the percent be other (catcode) to look for it.

773 \begingroup \makeatletter %
774 \catcode`\&=14 \catcode`\%=12 &

\lstdrv@eiffel@PrePL \lstdrv@eiffel@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.

775 \gdef\lstdrv@eiffel@PrePL{&
776 \lst@ifstring &
777  \expandafter\lstdrv@eiffel@TestPercent\lst@line%\relax &
778 \fi}&
779 \gdef\lstdrv@eiffel@TestPercent#1%#2\relax{&
780  \ifx\@empty#2\@empty \lst@PostPLDefault &
781  \else \expandafter\lstdrv@eiffel@CutPercent\lst@line\relax&
782  \fi}&

\lstdrv@eiffel@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.

783 \gdef\lstdrv@eiffel@CutPercent#1%#2\relax{&
784  \lst@stringfalse \lst@Tokenize#1\relax &
785  \lst@stringtrue \def\lst@line{%#2}}&
786 \endgroup %

787 ⟨/eiffel⟩

5.9 Elan

\lstdrv@elan@keys Since we need digits as letters, the keywords first:

788 ⟨∗elan⟩

789 \begingroup \makeatletter %
790 \lst@MakeDigitsLetter %
791 \gdef\lstdrv@elan@keys{ABS,AND,BOOL,CAND,CASE,CAT,COLUMNS,CONCR,CONJ,%
792  CONST,COR,DECR,DEFINES,DET,DIV,DOWNTO,ELIF,ELSE,END,ENDIF,ENDOP,%
793  ENDPACKET,ENDPROC,ENDREP,ENDSELECT,FALSE,FI,FILE,FOR,FROM,IF,INCR,%
794  INT,INV,LEAVE,LENGTH,LET,MOD,NOT,OF,OP,OR,OTHERWISE,PACKET,PROC,%
795  REAL,REP,REPEAT,ROW,ROWS,SELECT,SIGN,STRUCT,SUB,TEXT,THEN,TRANSP,%
796  TRUE,TYPE,UNTIL,UPTO,VAR,WHILE,WITH,XOR,%
797  maxint,sign,abs,min,max,random,initializerandom,subtext,code,%
798  replace,text,laenge,pos,compress,change,maxreal,smallreal,floor,pi,%
799  e,ln,log2,log10,sqrt,exp,tan,tand,sin,sind,cos,cosd,arctan,arctand,%
800  int,real,lastconversionok,put,putline,line,page,get,getline,input,%
801  output,sequentialfile,maxlinelaenge,reset,eof,close,complexzero,%
802  complexone,complexi,complex,realpart,imagpart,dphi,phi,vector,norm,%
803  replace,matrix,idn,row,column,sub,replacerow,replacecolumn,%
804  replaceelement,transp,errorsstop,stop}%
805 \endgroup %

\lstdrv@elan@ Now we define the main driver macro:

806 \begingroup \makeatletter %
807 \catcode`\"=12 %
808 \gdef\lstdrv@elan@{%
809  \keywords{\lstdrv@elan@keys}%
810  \sensitivetrue %
811  \DeclareCommentLine\relax %
812  \DeclareSingleComment stuff \relax %
813  \stringizer[d]{"}\lstbaseem{0.65}%
814  \lst@DefineCatcodes{\active}%
815  \let\lst@PrePL \lst@PrePLDefault %
816  \let\lst@PostPL\lst@PostPLDefault}%
817 \endgroup %

818 ⟨/elan⟩

5.10 Fortran

\lstdrv@fortran@keys Common ’keywords’ of Fortran 90 and Fortran 77:

819 ⟨∗fortran⟩

820 \begingroup \makeatletter %
821 \gdef\lstdrv@fortan@keys{ACCESS,ASSIGN,BACKSPACE,BLANK,BLOCK,CALL,%
822  CHARACTER,CLOSE,COMMON,COMPLEX,CONTINUE,DATA,DIMENSION,DIRECT,DO,%
823  DOUBLE,ELSE,END,ENTRY,EOF,EQUIVALENCE,ERR,EXIST,EXTERNAL,FILE,%
824  FMT,FORM,FORMAT,FORMATTED,FUNCTION,GO,TO,IF,IMPLICIT,INQUIRE,%
825  INTEGER,INTRINSIC,IOSTAT,LOGICAL,NAMED,NEXTREC,NUMBER,OPEN,OPENED,%
826  PARAMETER,PAUSE,PRECISION,PRINT,PROGRAM,READ,REAL,REC,RECL,%
827  RETURN,REWIND,SEQUENTIAL,STATUS,STOP,SUBROUTINE,THEN,TYPE,%
828  UNFORMATTED,UNIT,WRITE}%
829 \endgroup %
\lstdrv@fortran@ The driver macro:
830 \begingroup \makeatletter %
831 \catcode`\"=12 %
832 \gdef\lstdrv@fortran@{%
833  \keywords{\lstdrv@fortan@keys,ACTION,ADVANCE,ALLOCATE,ALLOCATABLE,%
834  ASSIGNMENT,CASE,CONTAINS,CYCLE,DEALLOCATE,DEFAULT,DELIM,EXIT,%
835  IN,NONE,IN,OUT,INTENT,INTERFACE,IOLENGTH,KIND,LEN,MODULE,NAME,%
836  NAMELIST,NMT,NULLIFY,ONLY,OPERATOR,OPTIONAL,OUT,PAD,POINTER,%
837  POSITION,PRIVATE,PUBLIC,READWRITE,RECURSIVE,RESULT,SELECT,%
838  SEQUENCE,SIZE,STAT,TARGET,USE,WHERE,WHILE,%
839  BLOCKDATA,DOUBLEPRECISION,ELSEIF,ENDBLOCKDATA,ENDDO,ENDFILE,%
840  ENDFUNCTION,ENDIF,ENDINTERFACE,ENDMODULE,ENDPROGRAM,ENDSELECT,%
841  ENDSUBROUTINE,ENDTYPE,ENDWHERE,GOTO,INOUT,SELECTCASE}%
842  \sensitivefalse %% not Fortran standard %%
843  \DeclareCommentLine !\relax %
844  \DeclareSingleComment stuff \relax %
845  \stringizer{"}\lstbaseem{0.6}%
846  \lst@DefineCatcodes{\active}%
847  \let\lst@PrePL \lstdrv@fortran@PrePL %
848  \let\lst@PostPL\lst@PostPLDefault}%
\lstdrv@fortran@90 \lstdrv@fortran@77 Macros for the optional argument:
849 \global\@namedef{lstdrv@fortran@90}{\lstdrv@fortran@}%
850 \global\@namedef{lstdrv@fortran@77}{\lstdrv@fortran@ %
851  \keywords{\lstdrv@fortan@keys,SAVE}%
852  \DeclareCommentLine\relax}%
853 \endgroup %
\lstdrv@fortran@PrePL \lstdrv@fortran@TestComment Again something different: We use the \lst@PrePL mechanism to handle ’∗’ and

’C’ comments. The defined test macro tests, if the first character of the input line is a star or an upper or lower case c. We output the line as comment and empty the input, if necessary. That’s all.

854 \begingroup \makeatletter %
855 \gdef\lstdrv@fortran@PrePL{%

856  \expandafter\lstdrv@fortran@TestComment\lst@line\relax}%
857 \catcode`\*=\active %
858 \gdef\lstdrv@fortran@TestComment#1#2\relax{\lst@commentfalse %
859  \ifx #1*\lst@commenttrue %
860  \else\if #1c\lst@commenttrue %% not Fortran standard %%
861  \else\if #1C\lst@commenttrue %
862  \fi \fi \fi %
863  \lst@ifcomment %
864  \expandafter\lst@Tokenize\lst@line\relax %
865  \let\lst@line\@empty \lst@commentfalse %
866  \fi}%
867 \endgroup %

868 ⟨/fortran⟩

5.11 Java

\lstdrv@java@ Nothing new.

869 ⟨∗java⟩

870 \begingroup \makeatletter %
871 \catcode`\"=12 \catcode`\*=\active %
872 \gdef\lstdrv@java@{%
873  \keywords{abstract,boolean,break,byte,case,catch,char,class,const,%
874  continue,default,do,double,else,extends,final,finally,float,%
875  for,goto,if,implements,import,instanceof,int,interface,long,%
876  native,new,null,package,private,protected,public,return,short,%
877  static,super,switch,synchronized,this,throw,throws,transient,%
878  try,void,volatile,while,true,false}%
879  \sensitivetrue %
880  \DeclareCommentLine //\relax %
881  \DeclareSingleComment /* */\relax %
882  \stringizer{"}\lstbaseem{0.6}%
883  \lst@DefineCatcodes{\active}%
884  \let\lst@PrePL \lst@PrePLDefault %
885  \let\lst@PostPL\lst@PostPLDefault}%
886 \endgroup %

887 ⟨/java⟩

5.12 Lisp

\lstdrv@lisp@ The keywords are the ’one-word’ functions and macros of Common Lisp, i.e. words not containing a minus. And I left out the caaaar, … functions.

888 ⟨∗lisp⟩

889 \begingroup \makeatletter %
890 \catcode`\"=12 \catcode`\-=11 %
891 \gdef\lstdrv@lisp@{%
892  \keywords{abort,abs,acons,acos,acosh,adjoin,alphanumericp,alter,%
893  append,apply,apropos,aref,arrayp,ash,asin,asinh,assoc,atan,%
894  atanh,atom,bit,boole,boundp,break,butlast,byte,catenate,%
895  ceiling,cerror,char,character,characterp,choose,chunk,cis,%

896  close,clrhash,coerce,collect,commonp,compile,complement,%
897  complex,complexp,concatenate,conjugate,cons,consp,constantp,%
898  continue,cos,cosh,cotruncate,count,delete,denominator,%
899  describe,directory,disassemble,documentation,dpb,dribble,%
900  ed,eighth,elt,enclose,endp,eq,eql,equal,equalp,error,eval,%
901  evalhook,evenp,every,exp,expand,export,expt,fboundp,fceiling,%
902  fdefinition,ffloor,fifth,fill,find,first,float,floatp,floor,%
903  fmakunbound,format,fourth,fround,ftruncate,funcall,functionp,%
904  gatherer,gcd,generator,gensym,gentemp,get,getf,gethash,%
905  identity,imagpart,import,inspect,integerp,intern,intersection,%
906  tively,isqrt,keywordp,last,latch,lcm,ldb,ldiff,length,list,%
907  listen,listp,load,log,logand,logbitp,logcount,logeqv,logior,%
908  lognand,lognor,lognot,logtest,logxor,macroexpand,makunbound,%
909  map,mapc,mapcan,mapcar,mapcon,maphash,mapl,maplist,mask,max,%
910  member,merge,min,mingle,minusp,mismatch,mod,namestring,%
911  nbutlast,nconc,nintersection,ninth,not,notany,notevery,%
912  nreconc,nreverse,nsublis,nsubst,nth,nthcdr,null,numberp,%
913  numerator,nunion,oddp,open,packagep,pairlis,pathname,pathnamep,%
914  phase,plusp,position,positions,pprint,previous,princ,print,%
915  proclaim,provide,random,rassoc,rational,rationalize,rationalp,%
916  read,readtablep,realp,realpart,reduce,rem,remhash,remove,%
917  remprop,replace,require,rest,revappend,reverse,room,round,%
918  rplaca,rplacd,sbit,scan,schar,search,second,series,set,seventh,%
919  shadow,signal,signum,sin,sinh,sixth,sleep,some,sort,split,%
920  sqrt,streamp,string,stringp,sublis,subseq,subseries,subsetp,%
921  subst,substitute,subtypep,svref,sxhash,symbolp,tailp,tan,tanh,%
922  tenth,terpri,third,truename,truncate,typep,unexport,unintern,%
923  union,until,values,vector,vectorp,warn,write,zerop,%
924  and,assert,case,ccase,cond,ctypecase,decf,declaim,defclass,%
925  defconstant,defgeneric,defmacro,defmethod,defpackage,%
926  defparameter,defsetf,defstruct,deftype,defun,defvar,do,dolist,%
927  dotimes,ecase,encapsulated,etypecase,flet,formatter,gathering,%
928  incf,iterate,labels,let,locally,loop,macrolet,mapping,or,pop,%
929  producing,prog,psetf,psetq,push,pushnew,remf,return,rotatef,%
930  setf,shiftf,step,time,trace,typecase,unless,untrace,when}%
931  \sensitivetrue % ???
932  \DeclareCommentLine;\relax %
933  \DeclareSingleComment stuff \relax %
934  \stringizer[b]{"}\lstbaseem{0.6}%
935  \lst@DefineCatcodes{11}%
936  \let\lst@PrePL \lst@PrePLDefault %
937  \let\lst@PostPL\lst@PostPLDefault}%
938 \endgroup %

939 ⟨/lisp⟩

5.13 Logo

\lstdrv@logo@ I don’t know where I have the keywords from and what kind of Logo it is. Help me!

940 ⟨∗logo⟩

941 \begingroup \makeatletter %
942 \gdef\lstdrv@logo@{% ??? end,unix
943  \keywords{and,atan,arctan,both,break,bf,bl,butfirst,butlast,cbreak,%
944  close,co,continue,cos,count,clearscreen,cs,debquit,describe,%
945  diff,difference,ed,edit,either,emptyp,equalp,er,erase,errpause,%
946  errquit,fifp,filefprint,fifty,fileftype,fip,fileprint,fird,%
947  fileread,fity,filetype,fiwd,fileword,f,first,or,fp,fprint,fput,%
948  fty,ftype,full,fullscreen,go,bye,goodbye,gprop,greaterp,help,%
949  if,iff,iffalse,ift,iftrue,nth,item,keyp,llast,lessp,list,local,%
950  lput,make,max,maximum,memberp,memtrace,min,minimum,namep,not,%
951  numberp,oflush,openr,openread,openw,openwrite,op,output,pause,%
952  plist,pots,pow,pprop,pps,pr,print,product,quotient,random,rc,%
953  readchar,rl,readlist,remprop,repcount,repeat,request,rnd,run,%
954  se,sentence,sentencep,setc,setcolor,setipause,setqpause,po,%
955  show,sin,split,splitscreen,sqrt,stop,sum,test,text,textscreen,%
956  thing,to,tone,top,toplevel,type,untrace,wait,word,wordp,%
957  yaccdebug,is,mod,remainder,trace,zerop,%
958  back,bk,bto,btouch,fd,forward,fto,ftouch,getpen,heading,hit,%
959  hitoot,ht,hideturtle,loff,lampoff,lon,lampon,lt,left,lot,%
960  lotoot,lto,ltouch,penc,pencolor,pd,pendown,pe,penerase,penmode,%
961  pu,penup,px,penreverse,rt,right,rto,rtouch,scrunch,seth,%
962  setheading,setscrun,setscrunch,setxy,shownp,st,showturtle,%
963  towardsxy,clean,wipeclean,xcor,ycor,tur,turtle,display,dpy}%
964  \sensitivefalse % ???
965  \DeclareCommentLine\relax %
966  \DeclareSingleComment stuff \relax %
967  \stringizer{}\lstbaseem{0.6}%
968  \lst@DefineCatcodes{\active}%
969  \let\lst@PrePL \lst@PrePLDefault %
970  \let\lst@PostPL\lst@PostPLDefault}%
971 \endgroup %

972 ⟨/logo⟩

5.14 Matlab

\lstdrv@matlab@keys \lstdrv@matlab@ Once more . . .

973 ⟨∗matlab⟩

974 \begingroup \makeatletter %
975 \lst@MakeDigitsLetter %
976 \gdef\lstdrv@matlab@keys{gt,lt,gt,lt,amp,%
977  abs,acos,acosh,acot,acoth,acsc,acsch,all,angle,ans,any,asec,asech,%
978  asin,asinh,atan,atan2,atanh,auread,auwrite,axes,axis,balance,bar,%
979  bessel,besselk,bessely,beta,betainc,betaln,blanks,bone,break,%
980  brighten,capture,cart2pol,cart2sph,caxis,cd,cdf2rdf,cedit,ceil,%
981  chol,cla,clabel,clc,clear,clf,clock,close,colmmd,Colon,colorbar,%
982  colormap,ColorSpec,colperm,comet,comet3,compan,compass,computer,%
983  cond,condest,conj,contour,contour3,contourc,contrast,conv,conv2,%
984  cool,copper,corrcoef,cos,cosh,cot,coth,cov,cplxpair,cputime,cross,%

 985  csc,csch,csvread,csvwrite,cumprod,cumsum,cylinder,date,dbclear,%
 986  dbcont,dbdown,dbquit,dbstack,dbstatus,dbstep,dbstop,dbtype,dbup,%
 987  ddeadv,ddeexec,ddeinit,ddepoke,ddereq,ddeterm,ddeunadv,deblank,%
 988  dec2hex,deconv,del2,delete,demo,det,diag,diary,diff,diffuse,dir,%
 989  disp,dlmread,dlmwrite,dmperm,dot,drawnow,echo,eig,ellipj,ellipke,%
 990  else,elseif,end,engClose,engEvalString,engGetFull,engGetMatrix,%
 991  engOpen,engOutputBuffer,engPutFull,engPutMatrix,engSetEvalCallback,%
 992  engSetEvalTimeout,engWinInit,eps,erf,erfc,erfcx,erfinv,error,%
 993  errorbar,etime,etree,eval,exist,exp,expint,expm,expo,eye,fclose,%
 994  feather,feof,ferror,feval,fft,fft2,fftshift,fgetl,fgets,figure,%
 995  fill,fill3,filter,filter2,find,findstr,finite,fix,flag,fliplr,%
 996  flipud,floor,flops,fmin,fmins,fopen,for,format,fplot,fprintf,fread,%
 997  frewind,fscanf,fseek,ftell,full,function,funm,fwrite,fzero,gallery,%
 998  gamma,gammainc,gammaln,gca,gcd,gcf,gco,get,getenv,getframe,ginput,%
 999  global,gplot,gradient,gray,graymon,grid,griddata,gtext,hadamard,%
1000  hankel,help,hess,hex2dec,hex2num,hidden,hilb,hist,hold,home,hostid,%
1001  hot,hsv,hsv2rgb,i,if,ifft,ifft2,imag,image,imagesc,Inf,info,input,%
1002  int2str,interp1,interp2,interpft,inv,invhilb,isempty,isglobal,%
1003  ishold,isieee,isinf,isletter,isnan,isreal,isspace,issparse,isstr,j,%
1004  jet,keyboard,kron,lasterr,lcm,legend,legendre,length,lin2mu,line,%
1005  linspace,load,log,log10,log2,loglog,logm,logspace,lookfor,lower,ls,%
1006  lscov,lu,magic,matClose,matDeleteMatrix,matGetDir,matGetFp,%
1007  matGetFull,matGetMatrix,matGetNextMatrix,matGetString,matlabrc,%
1008  matlabroot,matOpen,matPutFull,matPutMatrix,matPutString,max,mean,%
1009  median,menu,mesh,meshc,meshgrid,meshz,mexAtExit,mexCallMATLAB,%
1010  mexdebug,mexErrMsgTxt,mexEvalString,mexFunction,mexGetFull,%
1011  mexGetMatrix,mexGetMatrixPtr,mexPrintf,mexPutFull,mexPutMatrix,%
1012  mexSetTrapFlag,min,more,movie,moviein,mu2lin,mxCalloc,%
1013  mxCopyCharacterToPtr,mxCopyComplex16ToPtr,mxCopyInteger4ToPtr,%
1014  mxCopyPtrToCharacter,mxCopyPtrToComplex16,mxCopyPtrToInteger4,%
1015  mxCopyPtrToReal8,mxCopyReal8ToPtr,mxCreateFull,mxCreateSparse,%
1016  mxCreateString,mxFree,mxFreeMatrix,mxGetIr,mxGetJc,mxGetM,mxGetN,%
1017  mxGetName,mxGetNzmax,mxGetPi,mxGetPr,mxGetScalar,mxGetString,%
1018  mxIsComplex,mxIsFull,mxIsNumeric,mxIsSparse,mxIsString,%
1019  mxIsTypeDouble,mxSetIr,mxSetJc,mxSetM,mxSetN,mxSetName,mxSetNzmax,%
1020  mxSetPi,mxSetPr,NaN,nargchk,nargin,nargout,newplot,nextpow2,nnls,%
1021  nnz,nonzeros,norm,normest,null,num2str,nzmax,ode23,ode45,orient,%
1022  orth,pack,pascal,patch,path,pause,pcolor,pi,pink,pinv,plot,plot3,%
1023  pol2cart,polar,poly,polyder,polyeig,polyfit,polyval,polyvalm,pow2,%
1024  print,printopt,prism,prod,pwd,qr,qrdelete,qrinsert,quad,quad8,quit,%
1025  quiver,qz,rand,randn,randperm,rank,rat,rats,rbbox,rcond,real,%
1026  realmax,realmin,refresh,rem,reset,reshape,residue,return,rgb2hsv,%
1027  rgbplot,rootobject,roots,rose,rosser,rot90,rotate,round,rref,%
1028  rrefmovie,rsf2csf,save,saxis,schur,sec,sech,semilogx,semilogy,set,%
1029  setstr,shading,sign,sin,sinh,size,slice,sort,sound,spalloc,sparse,%
1030  spaugment,spconvert,spdiags,specular,speye,spfun,sph2cart,sphere,%
1031  spinmap,spline,spones,spparms,sprandn,sprandsym,sprank,sprintf,spy,%
1032  sqrt,sqrtm,sscanf,stairs,startup,std,stem,str2mat,str2num,strcmp,%
1033  strings,strrep,strtok,subplot,subscribe,subspace,sum,surf,surface,%
1034  surfc,surfl,surfnorm,svd,symbfact,symmmd,symrcm,tan,tanh,tempdir,%

1035  tempname,terminal,text,tic,title,tmp,toc,toeplitz,trace,trapz,tril,%
1036  triu,type,uicontrol,uigetfile,uimenu,uiputfile,unix,unwrap,upper,%
1037  vander,ver,version,view,viewmtx,waitforbuttonpress,waterfall,%
1038  wavread,wavwrite,what,whatsnew,which,while,white,whitebg,who,whos,%
1039  wilkinson,wk1read,wk1write,xlabel,xor,ylabel,zeros,zlabel,zoom}%
1040 \endgroup %
1041 \begingroup \makeatletter %
1042 \catcode`\"=12 %
1043 \gdef\lstdrv@matlab@{%
1044  \keywords{\lstdrv@matlab@keys}%
1045  \sensitivetrue %
1046  \DeclareCLPercent %
1047  \DeclareSingleComment stuff \relax %
1048  \stringizer{'}\lstbaseem{0.6}%
1049  \lst@DefineCatcodes{\active}%
1050  \let\lst@PrePL \lst@PrePLDefault %
1051  \let\lst@PostPL\lst@PostPLDefault}%
1052 \endgroup %

1053 ⟨/matlab⟩

5.15 Modula-2

\lstdrv@modula@ And once again . . .

1054 ⟨∗modula⟩

1055 \begingroup \makeatletter %
1056 \catcode`\"=12 \catcode`\*=\active %
1057 \gdef\lstdrv@modula@{%
1058  \keywords{AND,ARRAY,BEGIN,BY,CASE,CONST,DIV,DO,ELSE,ELSIF,END,EXIT,%
1059  EXPORT,FOR,FROM,IF,IMPLEMENTATION,IMPORT,IN,MOD,MODULE,NOT,OF,%
1060  OR,POINTER,PROCEDURE,QUALIFIED,RECORD,REPEAT,RETURN,SET,THEN,%
1061  TYPE,UNTIL,VAR,WHILE,WITH,ABS,BITSET,BOOLEAN,CAP,CARDINAL,CHAR,%
1062  CHR,DEC,EXCL,FALSE,FLOAT,HALT,HIGH,INC,INCL,INTEGER,LONGCARD,%
1063  LONGINT,LONGREAL,MAX,MIN,NIL,ODD,ORD,PROC,REAL,SIZE,TRUE,TRUNC,%
1064  VAL}%
1065  \sensitivetrue %
1066  \DeclareCommentLine\relax %
1067  \DeclareNestedComment (* *)\relax %
1068  \stringizer[d]{'"}\lstbaseem{0.65}%
1069  \lst@DefineCatcodes{\active}%
1070  \let\lst@PrePL \lst@PrePLDefault %
1071  \let\lst@PostPL\lst@PostPLDefault}%
1072 \endgroup %

1073 ⟨/modula⟩

5.16 Oberon-2

\lstdrv@oberon@ ’Nearly’ Modula-2:

1074 ⟨∗oberon⟩

1075 \begingroup \makeatletter %
1076 \catcode`\"=12 \catcode`\*=\active %
1077 \gdef\lstdrv@oberon@{%
1078  \keywords{ARRAY,BEGIN,BOOLEAN,BY,CASE,CHAR,CONST,DIV,DO,ELSE,ELSIF,%
1079  END,EXIT,FALSE,FOR,IF,IMPORT,IN,INTEGER,IS,LONGINT,LONGREAL,%
1080  LOOP,MOD,MODULE,NIL,OF,OR,POINTER,PROCEDURE,REAL,RECORD,REPEAT,%
1081  RETURN,SET,SHORTINT,THEN,TO,TRUE,TYPE,UNTIL,VAR,WHILE,WITH,%
1082  ABS,ASH,CAP,CHR,COPY,DEC,ENTIER,EXCL,HALT,INC,INCL,LEN,LONG,%
1083  MAX,MIN,NEW,ODD,ORD,SHORT,SIZE}
1084  \sensitivetrue %
1085  \DeclareCommentLine\relax %
1086  \DeclareNestedComment (* *)\relax %
1087  \stringizer[d]{'"}\lstbaseem{0.65}%
1088  \lst@DefineCatcodes{\active}%
1089  \let\lst@PrePL \lst@PrePLDefault %
1090  \let\lst@PostPL\lst@PostPLDefault}%
1091 \endgroup %

1092 ⟨/oberon⟩

5.17 Pascal

\lstdrv@pascal@ Since we already defined pascal comments in section 4.2, no catcodes must be changed here.

1093 ⟨∗pascal⟩

1094 \begingroup \makeatletter %
1095 \gdef\lstdrv@pascal@{%
1096  \keywords{alfa,and,array,begin,boolean,byte,case,char,const,div,do,%
1097  downto,else,end,false,file,for,function,get,goto,if,in,integer,%
1098  label,maxint,mod,new,not,of,or,pack,packed,page,program,%
1099  procedure,put,read,readln,real,record,repeat,reset,rewrite,set,%
1100  text,then,to,true,type,unpack,until,var,while,with,write,%
1101  writeln}%
1102  \sensitivefalse %
1103  \DeclareCommentLine\relax %
1104  \DeclareDoubleCommentPascal %
1105  \stringizer[d]{'}\lstbaseem{0.6}%
1106  \lst@DefineCatcodes{\active}%
1107  \let\lst@PrePL \lst@PrePLDefault %
1108  \let\lst@PostPL\lst@PostPLDefault}%
1109 \endgroup %

1110 ⟨/pascal⟩

5.18 Pascal XSC

\lstdrv@pxsc@ Tell me, if you want more words to be keywords.

1111 ⟨∗pxsc⟩

1112 \selectlisting{pascal}%
1113 \begingroup \makeatletter %
1114 \gdef\lstdrv@pxsc@{\lstdrv@pascal@ %

1115  \morekeywords{dynamic,external,forward,global,module,nil,operator,%
1116  priority,sum,type,use,dispose,mark,page,release,cimatrix,%
1117  cinterval,civector,cmatrix,complex,cvector,dotprecision,%
1118  imatrix,interval,ivector,rmatrix,rvector,string,im,inf,re,sup,%
1119  chr,comp,eof,eoln,expo,image,ival,lb,lbound,length,loc,mant,%
1120  maxlength,odd,ord,pos,pred,round,rval,sign,substring,succ,%
1121  trunc,ub,ubound}}%
1122 \endgroup %

1123 ⟨/pxsc⟩

5.19 Turbo Pascal

\lstdrv@tp@ The keywords are the reserved words and predefined functions and procedures of Turbo Pascal 6.0, I think. It’s a long list …

1124 ⟨∗tp⟩

1125 \selectlisting{pascal}%
1126 \begingroup \makeatletter %
1127 \gdef\lstdrv@tp@{\lstdrv@pascal@ %
1128  \morekeywords{asm,constructor,destructor,implementation,inline,%
1129  interface,nil,object,shl,shr,string,unit,uses,xor,%
1130  Abs,Addr,ArcTan,Chr,Concat,Copy,Cos,CSeg,DiskFree,DiskSize,%
1131  DosExitCode,DosVersion,DSeg,EnvCount,EnvStr,Eof,Eoln,Exp,%
1132  FExpand,FilePos,FileSize,Frac,FSearch,GetBkColor,GetColor,%
1133  GetDefaultPalette,GetDriverName,GetEnv,GetGraphMode,GetMaxMode,%
1134  GetMaxX,GetMaxY,GetModeName,GetPaletteSize,GetPixel,GetX,GetY,%
1135  GraphErrorMsg,GraphResult,Hi,ImageSize,InstallUserDriver,%
1136  InstallUserFont,Int,IOResult,KeyPressed,Length,Lo,MaxAvail,%
1137  MemAvail,MsDos,Odd,Ofs,Ord,OvrGetBuf,OvrGetRetry,ParamCount,%
1138  ParamStr,Pi,Pos,Pred,Ptr,Random,ReadKey,Round,SeekEof,SeekEoln,%
1139  Seg,SetAspectRatio,Sin,SizeOf,Sound,SPtr,Sqr,Sqrt,SSeg,Succ,%
1140  Swap,TextHeight,TextWidth,Trunc,TypeOf,UpCase,WhereX,WhereY,%
1141  Append,Arc,Assign,AssignCrt,Bar,Bar3D,BlockRead,BlockWrite,%
1142  ChDir,Circle,ClearDevice,ClearViewPort,Close,CloseGraph,ClrEol,%
1143  ClrScr,Dec,Delay,Delete,DelLine,DetectGraph,Dispose,DrawPoly,%
1144  Ellipse,Erase,Exec,Exit,FillChar,FillEllipse,FillPoly,%
1145  FindFirst,FindNext,FloodFill,Flush,FreeMem,FSplit,GetArcCoords,%
1146  GetAspectRatio,GetDate,GetDefaultPalette,GetDir,GetCBreak,%
1147  GetFAttr,GetFillSettings,GetFTime,GetImage,GetIntVec,%
1148  GetLineSettings,GetMem,GetPalette,GetTextSettings,GetTime,%
1149  GetVerify,GetViewSettings,GoToXY,Halt,HighVideo,Inc,InitGraph,%
1150  Insert,InsLine,Intr,Keep,Line,LineRel,LineTo,LowVideo,Mark,%
1151  MkDir,Move,MoveRel,MoveTo,MsDos,New,NormVideo,NoSound,OutText,%
1152  OutTextXY,OvrClearBuf,OvrInit,OvrInitEMS,OvrSetBuf,PackTime,%
1153  PieSlice,PutImage,PutPixel,Randomize,Rectangle,Release,Rename,%
1154  RestoreCrtMode,RmDir,RunError,Sector,Seek,SetActivePage,%
1155  SetAllPalette,SetBkColor,SetCBreak,SetColor,SetDate,SetFAttr,%
1156  SetFillPattern,SetFillStyle,SetFTime,SetGraphBufSize,%
1157  SetGraphMode,SetIntVec,SetLineStyle,SetPalette,SetRGBPalette,%
1158  SetTextBuf,SetTextJustify,SetTextStyle,SetTime,SetUserCharSize,%

1159  SetVerify,SetViewPort,SetVisualPage,SetWriteMode,Sound,Str,%
1160  SwapVectors,TextBackground,TextColor,TextMode,Truncate,%
1161  UnpackTime,Val,Window}}%
1162 \endgroup %

1163 ⟨/tp⟩

5.20 Perl

\lstdrv@perl@keys First the keywords, …

1164 ⟨∗perl⟩

1165 \begingroup \makeatletter %
1166 \lst@MakeDigitsLetter %
1167 \gdef\lstdrv@perl@keys{abs,accept,alarm,atan2,bind,binmode,bless,%
1168  caller,chdir,chmod,chomp,chop,chown,chr,chroot,close,closedir,%
1169  connect,continue,cos,crypt,dbmclose,dbmopen,defined,delete,die,do,%
1170  dump,each,else,elsif,endgrent,endhostent,endnetent,endprotoent,%
1171  endpwent,endservent,eof,eval,exec,exists,exit,exp,fcntl,fileno,%
1172  flock,for,foreach,fork,format,formline,getc,getgrent,getgrgid,%
1173  getgrnam,gethostbyaddr,gethostbyname,gethostent,getlogin,%
1174  getnetbyaddr,getnetbyname,getnetent,getpeername,getpgrp,getppid,%
1175  getpriority,getprotobyname,getprotobynumber,getprotoent,getpwent,%
1176  getpwnam,getpwuid,getservbyname,getservbyport,getservent,%
1177  getsockname,getsockopt,glob,gmtime,goto,grep,hex,if,import,index,%
1178  int,ioctl,join,keys,kill,last,lc,lcfirst,length,link,listen,local,%
1179  localtime,log,lstat,m,map,mkdir,msgctl,msgget,msgrcv,msgsnd,my,%
1180  next,no,oct,open,opendir,ord,pack,package,pipe,pop,pos,print,%
1181  printf,prototype,push,q,qq,quotemeta,qw,qx,rand,read,readdir,%
1182  readlink,recv,redo,ref,rename,require,reset,return,reverse,%
1183  rewinddir,rindex,rmdir,s,scalar,seek,seekdir,select,semctl,semget,%
1184  semop,send,setgrent,sethostent,setnetent,setpgrp,setpriority,%
1185  setprotoent,setpwent,setservent,setsockopt,shift,shmctl,shmget,%
1186  shmread,shmwrite,shutdown,sin,sleep,socket,socketpair,sort,splice,%
1187  split,sprintf,sqrt,srand,stat,study,sub,substr,symlink,syscall,%
1188  sysopen,sysread,system,syswrite,tell,telldir,tie,tied,time,times,%
1189  tr,truncate,uc,ucfirst,umask,undef,unless,unlink,unpack,unshift,%
1190  untie,until,use,utime,values,vec,wait,waitpid,wantarray,warn,while,%
1191  write,y}%
1192 \endgroup %

\lstdrv@perl@ … and now the main driver file macro.

1193 \begingroup \makeatletter %
1194 \catcode`\"=12 \catcode`\#=12 %
1195 \gdef\lstdrv@perl@{%
1196  \keywords{\lstdrv@perl@keys}%
1197  \sensitivetrue %
1198  \DeclareCommentLine#\relax %
1199  \DeclareSingleComment stuff \relax %
1200  \stringizer[b]{"'}\lstbaseem{0.6}%
1201  \lst@DefineCatcodes{\active}%

1202  \let\lst@PrePL \lstdrv@perl@PrePL %
1203  \let\lst@PostPL\relax}%
\lstdrv@perl@ifPOD \lstdrv@perl@PrepareListing We use a switch to indicate PODs. Every (Perl) listing \lst@Begin calls the
  macro \lstdrv@perl@PrepareListing to reset the switch.
1204 \gdef\lstdrv@perl@PODtrue{\let\lstdrv@perl@ifPOD\iftrue}%
1205 \gdef\lstdrv@perl@PODfalse{\let\lstdrv@perl@ifPOD\iffalse}%
1206 \gdef\lstdrv@perl@PrepareListing{\lstdrv@perl@PODfalse}%
\lstdrv@perl@PrePL \lstdrv@perl@TestComment \lstdrv@perl@TestCommentCut \lstdrv@perl@TestSharp Nothing else is really new now.
1207 \gdef\lstdrv@perl@PrePL{%
1208  \lst@ifstring %
1209  \lst@stringfalse \lst@ProcessWhitespaces \lst@stringtrue %
1210  \else\lstdrv@perl@ifPOD %
1211  \expandafter\lstdrv@perl@TestCommentCut\lst@line=cut\relax %
1212  \else \expandafter\lstdrv@perl@TestComment\lst@line\relax\relax %
1213  \fi \fi}%
1214 \gdef\lstdrv@perl@TestCommentCut#1=cut#2\relax{%
1215  \lst@commenttrue \expandafter\lst@Tokenize\lst@line\relax %
1216  \let\lst@line\@empty \lst@commentfalse %
1217  \ifx\@empty#2\@empty\else \lstdrv@perl@PODfalse \fi}%

We have to change some catcodes, to look for the sharp. In particular we need a new ’macro parameter symbol’ (&).

1218 \catcode`\$=11 \catcode`\&=6 \catcode`\#=12 %
1219 \gdef\lstdrv@perl@TestComment&1&2\relax{%
1220  \ifx &1=%
1221  \lstdrv@perl@PODtrue \lst@commenttrue %
1222  \expandafter\lst@Tokenize\lst@line\relax %
1223  \let\lst@line\@empty \lst@commentfalse %
1224  \else %
1225  \expandafter\lstdrv@perl@TestSharp\lst@line $#\relax %
1226  \fi}%

The \lowercase mechanism mentioned some time before to replace each $# with $#, where the latter # has letter catcode. This avoids wrong comment detection.

1227 \catcode`\~=11 \lccode`\~=`\#%
1228 \lowercase{%
1229 \gdef\lstdrv@perl@TestSharp&1$#&2\relax{%
1230  \ifx \@empty&2\@empty \else %
1231  \expandafter\lstdrv@perl@ReplaceSharp\lst@line\relax %
1232  \expandafter\lstdrv@perl@TestSharp\lst@line $#\relax %
1233  \fi}%
1234 \gdef\lstdrv@perl@ReplaceSharp&1$#&2\relax{\def\lst@line{&1$~&2}}%
1235 }\endgroup %

1236 ⟨/perl⟩

5.21 PL/I

\lstdrv@pli@keys \lstdrv@pli@ Same procedure . . .

1237 ⟨∗pli⟩

1238 \begingroup \makeatletter %
1239 \lst@MakeDigitsLetter %
1240 \gdef\lstdrv@pli@keys{ABS,ATAN,AUTOMATIC,AUTO,ATAND,BEGIN,BINARY,BIN,%
1241  BIT,BUILTIN,BY,CALL,CHARACTER,CHAR,CHECK,COLUMN,COL,COMPLEX,CPLX,%
1242  COPY,COS,COSD,COSH,DATA,DATE,DECIMAL,DEC,DECLARE,DCL,DO,EDIT,ELSE,%
1243  END,ENDFILE,ENDPAGE,ENTRY,EXP,EXTERNAL,EXT,FINISH,FIXED,%
1244  FIXEDOVERFLOW,FOFL,FLOAT,FORMAT,GET,GO,GOTO,IF,IMAG,INDEX,INITIAL,%
1245  INIT,INTERNAL,INT,LABEL,LENGTH,LIKE,LINE,LIST,LOG,LOG2,LOG10,MAIN,%
1246  MAX,MIN,MOD,NOCHECK,NOFIXEDOVERFLOW,NOFOFL,NOOVERFLOW,NOOFL,NOSIZE,%
1247  NOUNDERFLOW,NOUFL,NOZERODIVIDE,NOZDIV,ON,OPTIONS,OVERFLOW,OFL,PAGE,%
1248  PICTURE,PROCEDURE,PROC,PUT,READ,REPEAT,RETURN,RETURNS,ROUND,SIN,%
1249  SIND,SINH,SIZE,SKIP,SQRT,STATIC,STOP,STRING,SUBSTR,SUM,SYSIN,%
1250  SYSPRINT,TAN,TAND,TANH,THEN,TO,UNDERFLOW,UFL,VARYING,WHILE,WRITE,%
1251  ZERODIVIDE,ZDIV}%
1252 \endgroup %
1253 \begingroup \makeatletter %
1254 \catcode`\*=\active %
1255 \gdef\lstdrv@pli@{%
1256  \keywords{\lstdrv@pli@keys}%
1257  \sensitivefalse %
1258  \DeclareCommentLine\relax %
1259  \DeclareSingleComment /* */\relax %
1260  \stringizer{'}\lstbaseem{0.6}%
1261  \lst@DefineCatcodes{\active}%
1262  \let\lst@PrePL \lst@PrePLDefault %
1263  \let\lst@PostPL\lst@PostPLDefault}%
1264 \endgroup %

1265 ⟨/pli⟩

5.22 Simula

\lstdrv@simula@ Same as all the time.

1266 ⟨∗simula⟩

1267 \begingroup \makeatletter %
1268 \catcode`\"=12 %
1269 \gdef\lstdrv@simula@{%
1270  \keywords{activate,after,array,at,before,begin,boolean,character,%
1271  class,comment,delay,detach,do,else,end,external,false,for,go,%
1272  goto,if,in,inner,inspect,integer,is,label,name,new,none,notext,%
1273  otherwise,prior,procedure,qua,reactivate,real,ref,resume,%
1274  simset,simulation,step,switch,text,then,this,to,true,until,%
1275  value,virtual,when,while}%
1276  \sensitivefalse %
1277  \DeclareCommentLine\relax %
1278  \DeclareSingleComment stuff \relax %
1279  \stringizer{"'}\lstbaseem{0.65}%
1280  \lst@DefineCatcodes{\active}%
1281  \let\lst@PrePL \lst@PrePLDefault %

1282  \let\lst@PostPL\lst@PostPLDefault}%
\lstdrv@simula@67 \lstdrv@simula@cii \lstdrv@simula@dec \lstdrv@simula@ibm Macros for the options:
1283 \global\@namedef{lstdrv@simula@67}{\lstdrv@simula@}%
1284 \global\@namedef{lstdrv@simula@cii}{\lstdrv@simula@%
1285  \morekeywords{and,equiv,exit,impl,not,or,stop}}%
1286 \global\@namedef{lstdrv@simula@dec}{\lstdrv@simula@%
1287  \morekeywords{and,eq,eqv,ge,gt,hidden,imp,le,long,lt,ne,not,%
1288  options,or,protected,short}}%
1289 \global\@namedef{lstdrv@simula@ibm}{\lstdrv@simula@dec}%
1290 \endgroup %
\lstdrv@simula@PrepareListing \lstdrv@simula@OutputOther \lstdrv@simula@Output@ \lstdrv@simula@AppendOther@ Refer the section about Algol how comments are implemented.
1291 \begingroup \makeatletter %
1292 \gdef\lstdrv@simula@commenttrue{%
1293  \global\let\lstdrv@simula@ifcomment\iftrue}%
1294 \gdef\lstdrv@simula@commentfalse{%
1295  \global\let\lstdrv@simula@ifcomment\iffalse %
1296  \global\let\lstdrv@simula@closingcomment\@empty}%
1297 \gdef\lstdrv@simula@PrepareListing{%
1298  \lstdrv@simula@commentfalse %
1299  \let\lst@OutputOther\lstdrv@simula@OutputOther %
1300  \let\lst@Output\lstdrv@simula@Output@ %
1301  \let\lst@AppendOther\lstdrv@simula@AppendOther}%
1302 \gdef\lstdrv@simula@OutputOther{%
1303  \expandafter\def\expandafter\lst@text\expandafter{\the\lst@other}%
1304  \ifx\lst@text\@empty\else %
1305  \lstdrv@simula@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
1306  \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
1307  \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %
1308  \lst@MakeBox{}%
1309  \fi \fi \fi %
1310  \global\advance\lst@pos by -\lst@length %
1311  \lst@other{}\let\lst@text\@empty \lst@length0 %
1312  \fi}%
1313 \gdef\lstdrv@simula@Output@{%
1314  \ifx\lst@text\@empty\else %
1315  \lstdrv@simula@ifcomment %
1316  \ifx\@empty\lstdrv@simula@closingcomment %
1317  \lst@MakeBox{\lst@commentstyle}%
1318  \else %
1319  \expandafter\lst@ifoneof\lst@text\relax %
1320  {else,end,otherwise,when}%
1321  {\lstdrv@simula@commentfalse %
1322  \lst@MakeBox{\lst@keywordstyle}}%
1323  {\lst@MakeBox{\lst@commentstyle}}%
1324  \fi \else %
1325  \lst@ifstring \lst@MakeStringBox{\lst@stringstyle}\else %
1326  \lst@ifcomment\lst@MakeBox{\lst@commentstyle}\else %

1327  \expandafter\lst@KeywordOrNot\lst@text\relax %
1328  \expandafter\lst@ifoneof\lst@text\relax{comment,end}%
1329  {\lstdrv@simula@commenttrue %
1330  \expandafter\lst@ifoneof\lst@text\relax{end}%
1331  {\gdef\lstdrv@simula@closingcomment{a}}{}}%
1332  {}% empty else from 'ifoneof'
1333  \fi \fi \fi %
1334  \global\advance\lst@pos by -\lst@length %
1335  \let\lst@text\@empty \lst@length0 %
1336  \fi}%
1337 \gdef\lstdrv@simula@AppendOther#1{%
1338  \lstdrv@simula@ifcomment \if;#1%
1339  \lst@OutputOther \lstdrv@simula@commentfalse %
1340  \fi \fi %
1341  \advance\lst@length\@ne %
1342  \expandafter\lst@other\expandafter{\the\lst@other#1}}%
1343 \endgroup %

1344 ⟨/simula⟩

5.23 SQL

\lstdrv@sql@ Do you have corrections? Do you want more data base languages?

1345 ⟨∗sql⟩

1346 \begingroup \makeatletter %
1347 \catcode`\"=12 \catcode`\*=\active \catcode`\_=11 %
1348 \gdef\lstdrv@sql@{%
1349  \keywords{absolute,action,add,allocate,alter,are,assertion,at,%
1350  between,bit,bit_length,both,cascade,cascaded,case,cast,catalog,%
1351  char_length,character_length,coalesce,collate,collation,column,%
1352  connect,connection,constraint,constraints,convert,%
1353  corresponding,cross,current_date,current_time,%
1354  current_timestamp,current_user,date,day,deallocate,deferrable,%
1355  defered,describe,descriptor,diagnostics,disconnect,domain,drop,%
1356  else,end,exec,except,exception,execute,external,extract,false,%
1357  first,full,get,global,hour,identity,immediate,initially,inner,%
1358  input,insensitive,intersect,interval,isolation,join,last,%
1359  leading,left,level,local,lower,match,minute,month,names,%
1360  national,natural,nchar,next,no,nullif,octet_length,only,outer,%
1361  output,overlaps,pad,partial,position,prepare,preserve,prior,%
1362  read,relative,restrict,revoke,right,rows,scroll,second,session,%
1363  session_user,size,space,sqlstate,substring,system_user,%
1364  temporary,then,time,timestamp,timezone_hour,timezone_minute,%
1365  trailing,transaction,translate,translation,trim,true,unknown,%
1366  upper,usage,using,value,varchar,varying,when,write,year,zone}%
1367  \sensitivefalse %
1368  \DeclareCommentLine\relax %
1369  \DeclareSingleComment /* */\relax %
1370  \stringizer{'"}\lstbaseem{0.6}%
1371  \lst@DefineCatcodes{\active}%

1372  \let\lst@PrePL \lst@PrePLDefault %
1373  \let\lst@PostPL\lst@PostPLDefault}%
1374 \endgroup %

1375 ⟨/sql⟩

5.24 TEX

\lstdrv@tex@primitives \lstdrv@tex@commoncs \lstdrv@tex@latexcs We define the different classes of control sequences. The second macro holds the common control sequences of plain-TEX and L^{A}TEX 2ε.

1376 ⟨∗tex⟩

1377 \begingroup \makeatletter %
1378 \gdef\lstdrv@tex@primitives{above,abovedisplayshortskip,%
1379  abovedisplayskip,abovewithdelims,accent,adjdemerits,advance,%
1380  afterassignment,aftergroup,atop,atopwithdelims,badness,%
1381  baselineskip,batchmode,begingroup,belowdisplayshortskip,%
1382  belowdisplayskip,binoppenalty,botmark,box,boxmaxdepth,%
1383  brokenpenalty,catcode,char,chardef,cleaders,closein,closeout,%
1384  clubpenalty,copy,count,countdef,cr,crcr,csname,day,deadcycles,def,%
1385  defaulthyphenchar,defaultskewchar,delcode,delimiter,%
1386  delimiterfactor,delimitershortfall,dimen,dimendef,discretionary,%
1387  displayindent,displaylimits,displaystyle,displaywidowpenalty,%
1388  displaywidth,divide,doublehyphendemerits,dp,else,emergencystretch,%
1389  end,endcsname,endgroup,endinput,endlinechar,eqno,errhelp,%
1390  errmessage,errorcontextlines,errorstopmode,escapechar,everycr,%
1391  everydisplay,everyhbox,everyjob,everymath,everypar,everyvbox,%
1392  exhyphenpenalty,expandafter,fam,fi,finalhypendemerits,firstmark,%
1393  floatingpenalty,font,fontdimen,fontname,futurelet,gdef,global,%
1394  globaldefs,halign,hangafter,hangindent,hbadness,hbox,hfil,hfill,%
1395  hfilneg,hfuzz,hoffset,holdinginserts,hrule,hsize,hskip,hss,ht,%
1396  hyphenation,hyphenchar,hyphenpenalty,if,ifcase,ifcat,ifdim,ifeof,%
1397  iffalse,ifhbox,ifhmode,ifinner,ifmmode,ifnum,ifodd,iftrue,ifvbox,%
1398  ifvmode,ifvoid,ifx,ignorespaces,immediate,indent,input,insert,%
1399  insertpenalties,interlinepenalty,jobname,kern,language,lastbox,%
1400  lastkern,lastpenalty,lastskip,lccode,leaders,left,lefthyphenmin,%
1401  leftskip,leqno,let,limits,linepenalty,lineskip,lineskiplimits,long,%
1402  looseness,lower,lowercase,mag,mark,,mathaccent,mathbin,mathchar,%
1403  mathchardef,mathchoice,mathclose,mathcode,mathinner,mathop,%
1404  mathopen,mathord,mathpunct,mathrel,mathsurround,maxdeadcycles,%
1405  maxdepth,meaning,medmuskip,message,mkern,month,moveleft,moveright,%
1406  mskip,multiply,muskip,muskipdef,newlinechar,noalign,noboundary,%
1407  noexpand,noindent,nolimits,nonscript,nonstopmode,%
1408  nulldelimiterspace,nullfont,number,omit,openin,openout,or,outer,%
1409  output,outputpenalty,over,overfullrule,overline,overwithdelims,%
1410  pagedepth,pagefilllstretch,pagefillstretch,pagefilstretch,pagegoal,%
1411  pageshrink,pagestretch,pagetotal,par,parfillskip,parindent,%
1412  parshape,parskip,patterns,pausing,penalty,postdisplaypenalty,%
1413  predisplaypenalty,predisplaysize,pretolerance,prevdepth,prevgraf,%
1414  radical,raise,read,relax,relpenalty,right,righthyphenmin,rightskip,%
1415  romannumeral,scriptfont,scriptscriptfont,scriptscriptstyle,%

1416  scriptspace,scriptstyle,scrollmode,setbox,setlanguage,sfcode,%
1417  shipout,show,showbox,showboxbreadth,showboxdepth,showlists,showthe,%
1418  skewchar,skip,skipdef,spacefactor,spaceskip,span,special,%
1419  splitbotmark,splitfirstmark,splitmaxdepth,splittopskip,string,%
1420  tabskip,textfont,textstyle,the,thickmuskip,thinmuskip,time,toks,%
1421  toksdef,tolerance,topmark,topskip,tracingcommands,tracinglostchars,%
1422  tracingmacros,tracingonline,tracingoutput,tracingpages,%
1423  tracingparagraphs,tracingrestores,tracingstats,uccode,uchyph,%
1424  underline,unhbox,unhcopy,unkern,unpenalty,unskip,unvbox,unvcopy,%
1425  uppercase,vadjust,valign,vbadness,vbox,vcenter,vfil,vfill,vfilneg,%
1426  vfuzz,voffset,vrule,vsize,vskip,vsplit,vss,vtop,wd,widowpenalty,%
1427  write,xdef,xleaders,xspaceskip,year}%
1428 \gdef\lstdrv@tex@commoncs{active,acute,ae,AE,aleph,allocationnumber,%
1429  allowbreak,alpha,amalg,angle,approx,arccos,arcsin,arctan,arg,%
1430  arrowvert,Arrowvert,ast,asymp,b,backslash,bar,beta,bgroup,big,Big,%
1431  bigbreak,bigcap,bigcirc,bigcup,bigg,Bigg,biggl,Biggl,biggm,Biggm,%
1432  biggr,Biggr,bigl,Bigl,bigm,Bigm,bigodot,bigoplus,bigotimes,bigr,%
1433  Bigr,bigskip,bigskipamount,bigsqcup,bigtriangledown,bigtriangleup,%
1434  biguplus,bigvee,bigwedge,bmod,bordermatrix,bot,bowtie,brace,%
1435  braceld,bracelu,bracerd,braceru,bracevert,brack,break,breve,%
1436  buildrel,bullet,c,cap,cases,cdot,cdotp,cdots,centering,centerline,%
1437  check,chi,choose,circ,clubsuit,colon,cong,coprod,copyright,cos,%
1438  cosh,cot,coth,csc,cup,d,dag,dagger,dashv,ddag,ddagger,ddot,ddots,%
1439  deg,delta,Delta,det,diamond,diamondsuit,dim,displaylines,div,do,%
1440  dospecials,dot,doteq,dotfill,dots,downarrow,Downarrow,%
1441  downbracefill,egroup,eject,ell,empty,emptyset,endgraf,endline,%
1442  enskip,enspace,epsilon,equiv,eta,exists,exp,filbreak,flat,fmtname,%
1443  fmtversion,footins,footnote,footnoterule,forall,frenchspacing,%
1444  frown,gamma,Gamma,gcd,ge,geq,gets,gg,goodbreak,grave,H,hat,hbar,%
1445  heartsuit,hglue,hideskip,hidewidth,hom,hookleftarrow,%
1446  hookrightarrow,hphantom,hrulefill,i,ialign,iff,Im,imath,in,inf,%
1447  infty,int,interdisplaylinepenalty,interfootnotelinepenalty,intop,%
1448  iota,item,j,jmath,joinrel,jot,kappa,ker,l,L,lambda,Lambda,land,%
1449  langle,lbrace,lbrack,lceil,ldotp,ldots,le,leavevmode,leftarrow,%
1450  Leftarrow,leftarrowfill,leftharpoondown,leftharpoonup,leftline,%
1451  leftrightarrow,Leftrightarrow,leq,lfloor,lg,lgroup,lhook,lim,%
1452  liminf,limsup,line,ll,llap,lmoustache,ln,lnot,log,longleftarrow,%
1453  Longleftarrow,longleftrightarrow,Longleftrightarrow,longmapsto,%
1454  longrightarrow,Longrightarrow,loop,lor,lq,magstep,magstep,%
1455  magstephalf,mapsto,mapstochar,mathhexbox,mathpalette,mathstrut,%
1456  matrix,max,maxdimen,medbreak,medskip,medskipamount,mid,min,models,%
1457  mp,mu,multispan,nabla,narrower,natural,ne,nearrow,neg,negthinspace,%
1458  neq,newbox,newcount,newdimen,newfam,newif,newinsert,newlanguage,%
1459  newmuskip,newread,newskip,newtoks,newwrite,next,ni,nobreak,%
1460  nointerlineskip,nonfrenchspacing,normalbaselines,%
1461  normalbaselineskip,normallineskip,normallineskiplimit,not,notin,nu,%
1462  null,nwarrow,o,O,oalign,obeylines,obeyspaces,odot,oe,OE,%
1463  offinterlineskip,oint,ointop,omega,Omega,ominus,ooalign,openup,%
1464  oplus,oslash,otimes,overbrace,overleftarrow,overrightarrow,owns,P,%
1465  parallel,partial,perp,phantom,phi,Phi,pi,Pi,pm,pmatrix,pmod,Pr,%

1466  prec,preceq,prime,prod,propto,psi,Psi,qquad,quad,raggedbottom,%
1467  raggedright,rangle,rbrace,rbrack,rceil,Re,relbar,Relbar,%
1468  removelastskip,repeat,rfloor,rgroup,rho,rhook,rightarrow,%
1469  Rightarrow,rightarrowfill,rightharpoondown,rightharpoonup,%
1470  rightleftharpoons,rightline,rlap,rmoustache,root,rq,S,sb,searrow,%
1471  sec,setminus,sharp,showhyphens,sigma,Sigma,sim,simeq,sin,sinh,skew,%
1472  slash,smallbreak,smallint,smallskip,smallskipamount,smash,smile,sp,%
1473  space,spadesuit,sqcap,sqcup,sqrt,sqsubseteq,sqsupseteq,ss,star,%
1474  strut,strutbox,subset,subseteq,succ,succeq,sum,sup,supset,supseteq,%
1475  surd,swarrow,t,tan,tanh,tau,TeX,theta,Theta,thinspace,tilde,times,%
1476  to,top,tracingall,triangle,triangleleft,triangleright,u,underbar,%
1477  underbrace,uparrow,Uparrow,upbracefill,updownarrow,Updownarrow,%
1478  uplus,upsilon,Upsilon,v,varepsilon,varphi,varpi,varrho,varsigma,%
1479  vartheta,vdash,vdots,vec,vee,vert,Vert,vglue,vphantom,wedge,%
1480  widehat,widetilde,wlog,wp,wr,xi,Xi,zeta}%
1481 \gdef\lstdrv@tex@latexcs{a,AA,aa,addcontentsline,addpenalty,%
1482  addtocontents,addtocounter,addtolength,addtoversion,addvspace,alph,%
1483  Alph,and,arabic,array,arraycolsep,arrayrulewidth,arraystretch,%
1484  author,baselinestretch,begin,bezier,bfseries,bibcite,bibdata,%
1485  bibitem,bibliography,bibliographystyle,bibstyle,boldmath,%
1486  botfigrule,bottomfraction,Box,caption,center,CheckCommand,circle,%
1487  citation,cite,cleardoublepage,clearpage,cline,columnsep,%
1488  columnseprule,columnwidth,contentsline,dashbox,date,dblfigrule,%
1489  dblfloatpagefraction,dblfloatsep,dbltextfloatsep,dbltopfraction,%
1490  defaultscriptratio,defaultscriptscriptratio,depth,Diamond,%
1491  displaymath,document,documentclass,documentstyle,doublerulesep,em,%
1492  emph,endarray,endcenter,enddisplaymath,enddocument,endenumerate,%
1493  endeqnarray,endequation,endflushleft,endflushright,enditemize,%
1494  endlist,endlrbox,endmath,endminipage,endpicture,endsloppypar,%
1495  endtabbing,endtabular,endtrivlist,endverbatim,enlargethispage,%
1496  ensuremath,enumerate,eqnarray,equation,evensidemargin,extracolsep,%
1497  fbox,fboxrule,fboxsep,filecontents,fill,floatpagefraction,floatsep,%
1498  flushbottom,flushleft,flushright,fnsymbol,fontencoding,fontfamily,%
1499  fontseries,fontshape,fontsize,fontsubfuzz,footnotemark,footnotesep,%
1500  footnotetext,footskip,frac,frame,framebox,fussy,glossary,%
1501  headheight,headsep,height,hline,hspace,I,include,includeonly,index,%
1502  inputlineno,intextsep,itemindent,itemize,itemsep,iterate,itshape,%
1503  Join,kill,label,labelsep,labelwidth,LaTeX,LaTeXe,leadsto,lefteqn,%
1504  leftmargin,leftmargini,leftmarginii,leftmarginiii,leftmarginiv,%
1505  leftmarginv,leftmarginvi,leftmark,lhd,linebreak,linespread,%
1506  linethickness,linewidth,list,listfiles,listfiles,listparindent,%
1507  lrbox,makeatletter,makeatother,makebox,makeglossary,makeindex,%
1508  makelabel,MakeLowercase,MakeUppercase,marginpar,marginparpush,%
1509  marginparsep,marginparwidth,markboth,markright,math,mathbf,%
1510  mathellipsis,mathgroup,mathit,mathsf,mathsterling,mathtt,%
1511  mathunderscore,mathversion,mbox,mdseries,mho,minipage,multicolumn,%
1512  multiput,NeedsTeXFormat,newcommand,newcounter,newenvironment,%
1513  newfont,newhelp,newlabel,newlength,newline,newmathalphabet,newpage,%
1514  newsavebox,newtheorem,nobreakspace,nobreakspace,nocite,nocorr,%
1515  nocorrlist,nofiles,nolinebreak,nonumber,nopagebreak,normalcolor,%

1516  normalfont,normalmarginpar,numberline,obeycr,oddsidemargin,%
1517  oldstylenums,onecolumn,oval,pagebreak,pagenumbering,pageref,%
1518  pagestyle,paperheight,paperwidth,paragraphmark,parbox,parsep,%
1519  partopsep,picture,poptabs,pounds,protect,pushtabs,put,qbezier,%
1520  qbeziermax,r,raggedleft,raisebox,ref,refstepcounter,renewcommand,%
1521  renewenvironment,restorecr,reversemarginpar,rhd,rightmargin,%
1522  rightmark,rmfamily,roman,Roman,rootbox,rule,samepage,sbox,scshape,%
1523  secdef,sectionmark,selectfont,setcounter,settodepth,settoheight,%
1524  settowidth,sffamily,shortstack,showoutput,showoverfull,sloppy,%
1525  sloppypar,slshape,sqsubset,sqsupset,SS,stackrel,stepcounter,stop,%
1526  stretch,subparagraphmark,subsectionmark,subsubsectionmark,%
1527  suppressfloats,symbol,tabbing,tabbingsep,tabcolsep,tabular,%
1528  tabularnewline,textasciicircum,textasciitilde,textbackslash,%
1529  textbar,textbf,textbraceleft,textbraceright,textbullet,textcircled,%
1530  textcompwordmark,textdagger,textdaggerdbl,textdollar,textellipsis,%
1531  textemdash,textendash,textexclamdown,textfloatsep,textfraction,%
1532  textgreater,textheight,textit,textless,textmd,textnormal,%
1533  textparagraph,textperiodcentered,textquestiondown,textquotedblleft,%
1534  textquotedblright,textquoteleft,textquoteright,textregistered,%
1535  textrm,textsc,textsection,textsf,textsl,textsterling,%
1536  textsuperscript,texttrademark,texttt,textunderscore,textup,%
1537  textvisiblespace,textwidth,thanks,thefootnote,thempfn,thempfn,%
1538  thempfootnote,thepage,thepage,thicklines,thinlines,thispagestyle,%
1539  title,today,topfigrule,topfraction,topmargin,topsep,totalheight,%
1540  tracingfonts,trivlist,ttfamily,twocolumn,typein,typeout,unboldmath,%
1541  unitlength,unlhd,unrhd,upshape,usebox,usecounter,usefont,%
1542  usepackage,value,vector,verb,verbatim,vline,vspace,width}%
\texcs \moretexcs The definitions are similar to \keywords and \morekeywords.
1543 \gdef\texcs#1{\edef\lst@cs{,\zap@space#1 \@empty}}%
1544 \gdef\moretexcs#1{\edef\lst@cs{\lst@cs,\zap@space#1 \@empty}}%

\lstdrv@tex@ Main driver and option macros:

1545 \gdef\lstdrv@tex@{%
1546  \keywords{}%
1547  \texcs{\lstdrv@tex@primitives,\lstdrv@tex@commoncs,%
1548  advancepageno,beginsection,bf,bffam,bye,cal,cleartabs,columns,%
1549  dosupereject,endinsert,eqalign,eqalignno,fiverm,fivebf,fivei,%
1550  fivesy,folio,footline,hang,headline,it,itemitem,itfam,%
1551  leqalignno,magnification,makefootline,makeheadline,midinsert,%
1552  mit,mscount,nopagenumbers,normalbottom,of,oldstyle,pagebody,%
1553  pagecontents,pageinsert,pageno,plainoutput,preloaded,proclaim,%
1554  rm,settabs,sevenbf,seveni,sevensy,sevenrm,sl,slfam,supereject,%
1555  tabalign,tabs,tabsdone,tabsyet,tenbf,tenex,teni,tenit,tenrm,%
1556  tensl,tensy,tentt,textindent,topglue,topins,topinsert,tt,ttfam,%
1557  ttraggedright,vfootnote}%
1558  \sensitivetrue %
1559  \DeclareCLPercent %
1560  \DeclareSingleComment stuff \relax %
1561  \stringizer{}\lstbaseem{0.6}%

1562  \lst@DefineCatcodes{\active}%
1563  \let\lst@PrePL \relax %
1564  \let\lst@PostPL\relax}%
1565 \gdef\lstdrv@tex@plain{\lstdrv@tex@}%
1566 \gdef\lstdrv@tex@primitive{\lstdrv@tex@ \texcs{\lstdrv@tex@primitives}}%
1567 \gdef\lstdrv@tex@latex{\lstdrv@tex@ %
1568  \texcs{\lstdrv@tex@primitives,\lstdrv@tex@latexcs}}%
1569 \gdef\lstdrv@tex@allatex{\lstdrv@tex@ %
1570  \keywords{array,center,displaymath,document,enumerate,eqnarray,%
1571  equation,flushleft,flushright,itemize,list,lrbox,math,minipage,%
1572  picture,sloppypar,tabbing,tabular,trivlist,verbatim}%
1573  \texcs{\lstdrv@tex@primitives,\lstdrv@tex@latexcs,%
1574  AtBeginDocument,AtBeginDocument,AtBeginDvi,AtEndDocument,%
1575  AtEndOfClass,AtEndOfPackage,ClassError,ClassInfo,ClassWarning,%
1576  ClassWarningNoLine,CurrentOption,DeclareErrorFont,%
1577  DeclareFixedFont,DeclareFontEncoding,%
1578  DeclareFontEncodingDefaults,DeclareFontFamily,DeclareFontShape,%
1579  DeclareFontSubstitution,DeclareMathAccent,DeclareMathAlphabet,%
1580  DeclareMathAlphabet,DeclareMathDelimiter,DeclareMathRadical,%
1581  DeclareMathSizes,DeclareMathSymbol,DeclareMathVersion,%
1582  DeclareOldFontCommand,DeclareOption,DeclarePreloadSizes,%
1583  DeclareRobustCommand,DeclareSizeFunction,DeclareSymbolFont,%
1584  DeclareSymbolFontAlphabet,DeclareTextAccent,%
1585  DeclareTextAccentDefault,DeclareTextCommand,%
1586  DeclareTextCommandDefault,DeclareTextComposite,%
1587  DeclareTextCompositeCommand,DeclareTextFontCommand,%
1588  DeclareTextSymbol,DeclareTextSymbolDefault,ExecuteOptions,%
1589  GenericError,GenericInfo,GenericWarning,IfFileExists,%
1590  InputIfFileExists,LoadClass,LoadClassWithOptions,MessageBreak,%
1591  OptionNotUsed,PackageError,PackageInfo,PackageWarning,%
1592  PackageWarningNoLine,PassOptionsToClass,PassOptionsToPackage,%
1593  ProcessOptionsProvidesClass,ProvidesFile,ProvidesFile,%
1594  ProvidesPackage,ProvideTextCommand,RequirePackage,%
1595  RequirePackageWithOptions,SetMathAlphabet,SetSymbolFont,%
1596  TextSymbolUnavailable,UseTextAccent,UseTextSymbol}}%
1597 \endgroup %

\lstdrv@tex@PrepareListing Here we assign a different \lst@Output macro to detect control sequences. We also (re-) set some catcodes.

1598 \begingroup \makeatletter %
1599 \gdef\lstdrv@tex@PrepareListing{\let\lst@Output\lstdrv@tex@Output %
1600  \catcode`\0=12 \catcode`\1=12 \catcode`\2=12 \catcode`\3=12 %
1601  \catcode`\4=12 \catcode`\5=12 \catcode`\6=12 \catcode`\7=12 %
1602  \catcode`\8=12 \catcode`\9=12}%
\lstdrv@tex@Output \lstdrv@tex@CSOrNot These macros are similar to \lst@Output and \lst@CaseSensitiveKeywords.

We only do some adjustments, e.g. we need no ’ifstring’ test, since the stringizer is empty for TEX.

1603 \gdef\lstdrv@tex@Output{%

1604  \ifx\lst@text\@empty\else %
1605  \lst@ifcomment\lst@MakeBox{\lst@commentstyle}%
1606  \else\ifx\lst@lastother\lst@inputbackslash %
1607  \expandafter\lstdrv@tex@CSOrNot\lst@text\relax %
1608  \else\expandafter\lst@KeywordOrNot\lst@text\relax %
1609  \fi \fi %
1610  \global\advance\lst@pos by -\lst@length %
1611  \let\lst@text\@empty \lst@length0 %
1612  \fi}%
1613 \gdef\lstdrv@tex@CSOrNot#1\relax{%
1614  \def\lst@test##1,#1,##2\relax{%
1615  \ifx \@empty##2\@empty \lst@MakeBox{}%
1616  \else \lst@MakeBox{\lst@keywordstyle}%
1617  \fi}%
1618  \expandafter\lst@test\lst@cs,#1,\relax}%
1619 \endgroup

1620 ⟨/tex⟩

6 Extensions

Define a new driver file for an additional language. Refer the previous section how this is done.

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:

\lst@CommentLine 1. 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 \lst@line. After the call \lst@line must hold the noncomment rest and \lst@commentline the comment line. The C++ line

           if (comments!=appear) // comment stuff
       must be cut into ’if (comments!=appear) ’ and ’// comment stuff’.

\lst@SOC 2. Define the macro, which finds the start of a comment: The macro gets the input via the macro \lst@line. After the call \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 \lst@comment. If a comment is separated (not if and only if), you have to call \lst@commenttrue. The Pascal line

           if { comment } appears then
       is cut into ’if ’ and ’{ comment } appears then’.

\lst@EOC 3. Define the macro, which finds the end of a comment: The macro gets the input via the macro \lst@line. After the call \lst@comment must hold the comment and \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 \lst@commentfalse. The Pascal line

           { comment } appears then

must be cut into ’{ comment }’ and ’ appears then’. Assign these macros to \lst@CommentLine, \lst@SOC and \lst@EOC within your language command.

7 History

Only major changes after version 0.15 are listed here. Previous changes are still present in the .dtx-file.

0.16 from 1997/06/01

– Thanks to Anders Edenbrandt^{5} for reporting two bugs: lstmodula.sty corrected (misspelled \`") and call of \lst@???styles in \lst@Begin avoid loading of font files when catcodes are changed.

– Thanks to Rolf Niepraschk^{6} for reporting wrong catcode of $. I’ve also changed catcode of @ and took over the proposal of using \zap@space. The catcode of the percent % is restored after typesetting a listing now.

– Thanks to Knut Müller^{7} and Stefan Meister^{8} for reporting problem with the command \blankstringtrue. The problem is gone.

– new commands \spreadlisting, \listoflistings, \labelstyle, \thelstline,
  \lstbaseem, \listlistingsname

– listing environment rewritten

0.17 from 1997/09/29

– \spreadlisting works correct now (e.g. page numbers move not right any more),

  new commands \selectlisting and \lstlineskip, \labelstyle changed

– speed up things (quick ’if parameter empty’, all \long except one removed, faster

  \lst@GotoNextTabStop, etc.)

– alignment of wide other characters improved (e.g. ==)

– many new languages: Ada, Algol, Cobol, Comal 80, Elan, Fortran 77, Lisp, Logo, Matlab, Oberon, Perl, PL/I, Simula, SQL, TEX

References

[1] Barnes, John Gilbert Presslie: Programming in Ada plus language reference manual \begin{matrix}c \\ ◯ \end{matrix} 1991 Addison-Wesley Publishing Company, Inc.; ISBN 0-201-56539-0

[2] Uwe Pape: Programmieren in ALGOL 60 \begin{matrix}c \\ ◯ \end{matrix} 1973 Carl Hanser Verlag München; ISBN 3-446-11605-2

[3] Frank G. Pagan: A practical guide to ALGOL 68 \begin{matrix}c \\ ◯ \end{matrix} 1976 by John Wiley & Sohn Ltd.; ISBN 0-471-65746-8 (Cloth); ISBN 0-471-65747-6 (Pbk)

[4] Borge R. Christensen: Strukturierte Programmierung mit COMAL 80 [aus dem Dänischen übertragen und bearbeitet von Margarete Kragh] 2., verb. Auflage – München; Wien: Oldenburg, 1985; ISBN 3-486-26902-X

[5] Bertrand Meyer: Eiffel: the language Prentice Hall International (UK) Ldt, 1992; ISBN 0-13-247925-7 [6] Leo H. Klingen, Jochen Liedtke: Programmieren mit ELAN

5Department of Computer Science Lund University, Sweden. Anders.Edenbrandt@dna.lth.se 6Physikalisch–Technische Bundesanstalt Berlin, Germany. Niepraschk@ptb.de 7knut@physik3.gwdg.de 8FH–Wolfenbüttel, Germany.

B.G. Teubner, Stuttgart 1983; ISBN 3-519-02507-8

[7] Karl Hans Müller: Fortran 77: Programmierungsanleitung 3., völlig neu bearb. Aufl. – Mannheim; Wien; Zürich: Bibliographisches Institut, 1984; ISBN 3-411-05804-8

[8] Thomas Michel: Fortran 90: Lehr– und Handbuch Mannheim; Leipzig; Wien; Zürich: BI-Wiss.-Verlag, 1994; ISBN 3-411-16861-7

 [9] http://www.utexas.edu/math/Matlab/Manual

[10] Niklaus Wirth: Programmieren in Modula-2, Übers. Guido Pfeiffer 2. Auflage – Berlin; Heidelberg; New York; London; Paris; Tokyo; Hong Kong: Springer, 1991; ISBN 3-540-51689-1

[11] http://java.sun.com

[12] Guy Steele: Common Lisp Copyright 1990 by Digital Equipment Corporation; ISBN 1-55558-042-4

[13] http://www.perl.com

[14] Bernhard Fischer, Herman Fischer: Structured Programming in PL/I and PL/C Copyright \begin{matrix}c \\ ◯ \end{matrix} 1976 by Marcel Dekker, Inc.; ISBN 0-8247-6394-7

[15] Günther Lamprecht: Introduction to SIMULA 67 Braunschweig; Wiesbaden: Vieweg, 1981

[16] Jim Melton, Alan R. Simon: Understanding the new SQL: A Complete Guide \begin{matrix}c \\ ◯ \end{matrix} 1993 Morgan Kaufmann Publishers, Inc.; ISBN 1-55860-245-3

[17] Rainer Schöpf, Bernd Raichle, Chris Rowley: A New Implementation of L^{A}TEX’s verbatim and verbatim* Environments.

Index

Numbers written in italic refer to the page where the corresponding entry is described, the ones underlined to the code line of the definition, the rest to the code lines where the entry is used.

Symbols

\@firstoftwo . . . . . . 110, 116, 129, 132 \@namedef . . . . . 527, 528, 719, 720,

849, 850, 1283, 1284, 1286, 1289 \@secondoftwo . . . . . 109, 115, 130, 133 \@tempcnta …. 261–263, 265, 266, 269 \@tempdima . . . . . . . . . . 257, 259, 264 \@whilenum . . . . . . . . . . . . . . 209, 427

B

\batchmode . . . . . . . . . . . . . . . . . . 194

\blankstringfalse . . . . . . 6, \underline{163}, 175
\blankstringtrue . . . . . . . . . . . 6, \underline{163}

C \commentstyle . . . . . . . . . . 6, \underline{134}, 172

D

                                       \DeclareCLPercent . . . . \underline{89}, 1046, 1559
                                       \DeclareCommentLine . . . . . . . . . . .

. . . . . 9, \underline{15}, 89, 480, 500, 521, 614, 646, 713, 745, 766, 811, 843, 852, 880, 932, 965, 1066, 1085, 1103, 1198, 1258, 1277, 1368

                                       \DeclareDoubleComment . . . . . 9, \underline{55}, 92
                                       \DeclareDoubleCommentPascal  \underline{90}, 1104

\DeclareNestedComment 9, \underline{70}, 1067, 1086
\DeclarePairedComment . . . . 9, \underline{51}, 522
\DeclareSingleComment . . . . . . . 9,

\underline{50}, 481, 501, 532, 615, 714, 746, 767, 812, 844, 881, 933, 966, 1047, 1199, 1259, 1278, 1369, 1560

E

environments:

listing . . . . . . . . . . . . . . . . . . . 5 \errorstopmode . . . . . . . . . . . . . . . 194 \everypar . . . . . . . . . . . . . . . 259, 264

I

\iflisting . . . . . . . . . \underline{1}, 193, 224, 243 \inputlisting . . . . . . . . . . . . . . 5, \underline{191}

K

\keywords . . . . . . 8, \underline{149}, 478, 492, 512, 529, 609, 711, 721, 740, 757, 809, 833, 851, 873, 892, 943, 1044, 1058, 1078, 1096, 1196, 1256, 1270, 1349, 1546, 1570

\keywordstyle . . . . . . . . . . 6, \underline{134}, 172

L

\labelstyle . . . . . . . . . . . . 7, \underline{134}, 173 \listing . . . . . . . . . . . . . . . . . . . . \underline{223} listing (environment) . . . . . . . . . . . 5 \listingfalse . . . . . . . . . . . . . . . . . 5 \listingtrue . . . . . . . . . . . . . . . 5, 469

\listlistingsname . . . 6, 179–181, 183

\listoflistings . . . . . . . . . . . . 6, \underline{176}

\ListOfListingsLine . . . . . . . 186, 189

\lowercase . . . . . . . . . . . . . 235, 1228

\lst@AllLineProcessing 219, 243, \underline{277}
\lst@AppendOther . . . . . . 335, 351,

\underline{355}, 358, 367, 370, 376, 544, 1301 \lst@baseem . . . . . . . . . . . . . . 145, 271 \lst@Begin . . . . . . . . . . 207, 229, \underline{249}

\lst@bTestStringizer . . . . . . . . . . \underline{357}
\lst@CaseSensitiveKeywords . . \underline{94}, 168

\lst@ccPercent . . . . . . . . . . . 275, 465

\lst@ChangeCatcodes . . . . . . . 272, \underline{442}
\lst@ChangeMoreCatcodes . . . 441, 466
\lst@closing@stringizer 359, 371, 382

\lst@comment . \underline{14}, 38, 43, 48, 54, 75,

82, 253, 291, 292, 299, 300, 306, 309

\lst@commentdepth . . \underline{7}, 80, 81, 85, 252

\lst@commentfalse 9, 48, 81, 252, 295,

297, 307, 732, 858, 865, 1216, 1223

\lst@CommentLine . . . . \underline{15}, 17, 63, 294
\lst@commentline . . . . . . . . . . . . .

\underline{14}, 20, 24, 253, 299, 300, 303, 306

\lst@commentstyle . . . . . . . . . . . .

. 135, 255, 389, 399, 423, 549, 551, 563, 566, 578, 583, 586, 1305, 1307, 1317, 1323, 1326, 1605

\lst@commenttrue . . . . . . 8, 38, 54,

291, 304, 731, 859–861, 1215, 1221 \lst@CountSOC . . . . . . . . . . . 73, 83, 86 \lst@cs . . . . . . . . . . . 1543, 1544, 1618 \lst@curr . . . . . . . . 127, 129, 187, 273 \lst@CutCL . . . . . . . . . . . . . . . \underline{15}, 17 \lst@CutEOC . . . . . . . . . . . . . . . . 77, 79 \lst@CutSOC . . . . . . . . . . . . . . . . 53, 66

\lst@DefineCatcodes . . . . . . . . . . .

. . . . . . . . \underline{440}, 483, 503, 524, 617, 716, 748, 769, 814, 846, 883, 935, 968, 1049, 1069, 1088, 1106, 1201, 1261, 1280, 1371, 1562

\lst@DefineSingleComment . . . . . . .

. . . . . . . . . . \underline{26}, 50, 52, 56, 57, 71

\lst@DoStringizerTest . 366, 375, \underline{378}
\lst@dTestStringizer . . . . . . . . . . \underline{369}

\lst@End . . . . . . . . . . . . 221, 246, \underline{249}

\lst@endinputfalse . . . . . . . . . . 5, 212
\lst@endinputtrue . . . . . . 4, 215, 216
\lst@EndTestWhitespace . . . . \underline{317}, 323

\lst@EOC . . . . . . \underline{26}, 60, 63, 63, 67, 290 \lst@EOC@ . . . . . . . . . . . . . . . . . . . 58 \lst@FillBox . . . . . . . . . 407, \underline{408}, 418

\lst@GotoNextTabStop 319, 331, 346, \underline{426}

\lst@greater . . . . . . . . . . . . . 433, 457

\lst@halfspread . . . . . . . . . . . . . .

. . . . . \underline{13}, 151, 152, 257, 259, 264

\lst@HookComment . . . . . . . . . . . 58, \underline{59}

\lst@ifcomment … \underline{7}, 63, 290, 292, 309, 335, 351, 389, 399, 423, 551, 566, 586, 863, 1307, 1326, 1605

\lst@ifendinput . . . . . . . . . . . . \underline{1}, 217 \lst@IfOneOf . . . . . . . . . . . . . . . . . \underline{107} \lst@ifoneof . . . . . . . . . . . . . \underline{107},

568, 580, 588, 590, 1319, 1328, 1330 \lst@ifoption . . . . . . . . . . . . \underline{128}, 543 \lst@ifselect . . . . . . . . . . . . . . . . \underline{128} \lst@ifstring . . . . . . . . . . . \underline{7}, 285,

296, 358, 370, 388, 398, 421, 550, 565, 585, 776, 1208, 1306, 1325

\lst@inputbackslash . . . 360, 447, 1606

\lst@inputblank . . . . . . . . . . 349, 449 \lst@inputfile . . . . . . . . . . . . . . .

… \underline{1}, 194, 195, 200, 210, 214, 215

\lst@KeywordOrNot . . . . . . . . . . . .

168, 170, 390, 567, 587, 1327, 1608 \lst@keywords . . 99, 106, 154, 156, 630

\lst@keywordstyle . . . . . . 97, 103,

134, 255, 562, 582, 629, 1322, 1616 \lst@labelstep . 138, 258, 261–263, 266 \lst@labelstyle . . . . . . 137, 256, 267 \lst@lastno . . . . . . . . . . . . \underline{6}, 208, 216 \lst@lastother …. 280, 342, 349,

360, 363, 365, 369, 371, 380, 1606 \lst@leftbrace . . . . . . . . . . . 430, 454 \lst@length . . . . . . . . \underline{12}, 279, 328,

335, 343, 355, 392, 393, 402, 403, 406, 417, 421, 554, 555, 571, 572, 594, 595, 601, 1310, 1311, 1334, 1335, 1341, 1610, 1611

\lst@less . . . . . . . . . . . . . . . 432, 456 \lst@line … \underline{14}, 18, 21, 24, 32, 35,

38, 40, 43, 45, 48, 54, 66, 75, 77, 82, 210, 214, 218, 222, 243, 278, 295, 301, 309, 314, 316, 317, 322, 623, 628, 631, 727, 731, 732, 777, 781, 785, 856, 864, 865, 1211, 1212, 1215, 1216, 1222, 1223, 1225, 1231, 1232, 1234

\lst@lineno . . . . . . . . . . . . . . . . . .

… \underline{6}, 209, 211, 216, 254, 267, 282 \lst@lineskip . . . . . . . . . . . . 148, 251

\lst@ListOfListingsEntry \underline{184}, 192, 239

\lst@MakeBox . . . . . . . . . . . . . . . . . … 96, 97, 102, 103, 164, 389, 399, 400, \underline{405}, 549, 551, 552, 562, 563, 566, 578, 582, 583, 586, 1305, 1307, 1308, 1317, 1322, 1323, 1326, 1605, 1615, 1616

\lst@MakeDigitsLetter . . . . . . . . .

\underline{437}, 463, 656, 790, 975, 1166, 1239

\lst@MakeSpecialStringBox . . 166, \underline{416}
\lst@MakeStringBox . 164, 166, 388,

398, 422, 550, 565, 585, 1306, 1325 \lst@minus . . . . . . . . . . . . . . 435, 459 \lst@multiply . . . . . . . . . . . . 436, 460 \lst@next . . . . . 244, 246, 247, 326,

333, 334, 338, 340, 344, 348, 354

\lst@NonCaseSensitiveKeywords . .

. . . . . . . . . . . . . . . . . . . \underline{100}, 170 \lst@opt . . . . . . . . . . . . . . . . 127, 132 \lst@other . . . . . . . . \underline{14}, 356, 396,

403, 547, 555, 602, 1303, 1311, 1342 \lst@Output . . . . . . . . . . . . . . . . . .

… 330, \underline{386}, 543, 545, 1300, 1599 \lst@outputblank . . 320, 417, 450, 452 \lst@OutputChar … 314, 320, \underline{419}, 629

\lst@OutputOther . . . . . . . . . . . . .

. . . . . 342, 346, 348, 350, 361, 372, 381, \underline{395}, 542, 599, 1299, 1339

\lst@pos \underline{12}, 279, 392, 402, 419, 427–

429, 554, 571, 594, 1310, 1334, 1610

\lst@postlisting . . . . . . . . . 150, 275

\lst@PostPL …. 281, 485, 505, 526, 619, 718, 750, 771, 816, 848, 885, 937, 970, 1051, 1071, 1090, 1108, 1203, 1263, 1282, 1373, 1564

\lst@PostPLDefault . . . . . . . . \underline{283},

485, 505, 526, 619, 750, 780, 816, 848, 885, 937, 970, 1051, 1071, 1090, 1108, 1263, 1282, 1373

\lst@prelisting . . . . . . . . . . 149, 250 \lst@PrePL …. 281, 484, 504, 525,

618, 717, 749, 770, 815, 847, 884, 936, 969, 1050, 1070, 1089, 1107, 1202, 1262, 1281, 1372, 1563

\lst@PrePLDefault \underline{283}, 484, 504, 525,

749, 815, 884, 936, 969, 1050, 1070, 1089, 1107, 1262, 1281, 1372

\lst@ProcessLine . . . . . 281, \underline{289}, 630
\lst@ProcessListing . . . . . . . 199, \underline{206}
\lst@ProcessWhitespaces . . \underline{315}, 1209

\lst@RemovePar . . . . . . . . . . . 218, \underline{222} \lst@rightbrace . . . . . . . . . . 431, 455 \lst@SavedEOC . . . . . . . . . . . . . . . . 58 \lst@SOC . . . . . . . . . . . . . . \underline{26}, 63, 294

\lst@stringfalse . . . . . . . . . . . . .

. 11, 252, 287, 361, 372, 784, 1209 \lst@stringizer . . . . . . 162, 366, 375

\lst@stringstyle . . 136, 256, 388,

398, 422, 550, 565, 585, 1306, 1325 \lst@stringtrue … 10, 381, 785, 1209 \lst@tablength . . . . . . . . . . . 142, 428 \lst@test . . . . . . . . . . . . . . . . . . .

95, 99, 101, 106, 108, 112, 114, 118, 128, 129, 131, 132, 1614, 1618

\lst@TestCL . . . . . . . . . . . . . . . \underline{15}, 17 \lst@TestEOC . . . . . . . . . . . . . . . . . 72 \lst@TestSOC . . . . . . . . . . . . . . . . . 61 \lst@TestSOC@ . . . . . . . . . . . . . . . . 58

\lst@TestStringizer . . . 161, 336, 352
\lst@TestWhitespace . . . . . . . 316, \underline{318}

\lst@text . . . . . 279, 328, 343, 387, 390, 393, 396, 397, 403, 407, 418, 421, 547, 548, 555, 558, 560, 567–569, 572, 575, 580, 587, 588, 590, 595, 1303, 1304, 1311, 1314, 1319, 1327, 1328, 1330, 1335, 1604, 1607, 1608, 1611

\lst@Tokenize . . . . . 291, 295, 305,

\underline{326}, 344, 731, 784, 864, 1215, 1222

\lst@TokenizeOther . . . . . . . . 334, \underline{339}
\lst@TypesetChar . . . . . . . . . 298, \underline{314}
\lst@verticalbar . . . . . . . . . 434, 458

\lst@width . \underline{12}, 271, 406, 417, 420, 429 \lstbaseem . . 7, \underline{142}, 482, 502, 523,

616, 715, 747, 768, 813, 845, 882, 934, 967, 1048, 1068, 1087, 1105, 1200, 1260, 1279, 1370, 1561

\lstdrv@ . . . . . . . . . . . . . . . . 123, 126 \lstdrv@ada@ . . . . . . . . . . . . . . . . . \underline{488} \lstdrv@algol@ . . . . . . . \underline{508}, 527, 528

\lstdrv@algol@60 . . . . . . . . . . . . . \underline{527}
\lstdrv@algol@68 . . . . . . . . . . . . . \underline{527}
\lstdrv@algol@AppendOther . . 544, 597
\lstdrv@algol@AppendOther@ . . . . . \underline{597}
\lstdrv@algol@closingcomment . . .

. . . . . . . . . . . . 539, 560, 569, 577

\lstdrv@algol@commentfalse . . . . .

. . . . . . . . 537, 541, 561, 581, 599

\lstdrv@algol@commenttrue . . . . . . 535
\lstdrv@algol@ifcomment . . . . . . .

. . . . . 536, 538, 549, 559, 576, 598

\lstdrv@algol@Output . . . . . . 545, \underline{557}
\lstdrv@algol@Output@ . . . . . 543, \underline{574}
\lstdrv@algol@OutputOther . . 542, \underline{546}
\lstdrv@algol@PrepareListing . . . \underline{534}

\lstdrv@blank@ . . . . . . . . . . . . . . . \underline{475} \lstdrv@c@ . . . . . . . . . . . . . . \underline{605}, 639

\lstdrv@c@directives . . . . . . \underline{621}, 630

\lstdrv@c@PrePL . . . . . . . . . . 618, \underline{621}

\lstdrv@c@TestSharp . . . . . . . 623, \underline{626}

\lstdrv@cobol@ …. \underline{708}, 719, 720, 722

\lstdrv@cobol@1974 . . . . . . . . . . . . \underline{719}
\lstdrv@cobol@1985 . . . . . . . . . . . . \underline{719}
\lstdrv@cobol@ibm . . . . . . . . . . . . \underline{719}
\lstdrv@cobol@keys . . . . \underline{654}, 711, 721
\lstdrv@cobol@keys@eightyfive . .

. . . . . . . . . . . . . . . . . . . \underline{654}, 711

\lstdrv@cobol@keys@ibm . . . . \underline{654}, 723

\lstdrv@cobol@PrePL . . . . . . . 717, \underline{725}
\lstdrv@cobol@TestComment . . . . . . \underline{725}

\lstdrv@comal@ . . . . . . . . . . . . . . . \underline{736} \lstdrv@cpp . . . . . . . . . . . . . . 647, 648 \lstdrv@cpp@ . . . . . . . . . . . . . . . . . \underline{635}

\lstdrv@cpp@ansi . . . . . . . . . . . . . 647

\lstdrv@cpp@vc . . . . . . . . . . . . . . . 648 \lstdrv@eiffel@ . . . . . . . . . . . . . . \underline{753}

\lstdrv@eiffel@CutPercent . . 781, \underline{783}
\lstdrv@eiffel@PrePL . . . . . . 770, \underline{775}
\lstdrv@eiffel@TestPercent . . . . . \underline{775}

\lstdrv@elan@ . . . . . . . . . . . . . . . . \underline{806}

\lstdrv@elan@keys . . . . . . . . \underline{788}, 809
\lstdrv@fortan@keys . . . 821, 833, 851
\lstdrv@fortran@ . . . . . \underline{830}, 849, 850
\lstdrv@fortran@77 . . . . . . . . . . . . \underline{849}
\lstdrv@fortran@90 . . . . . . . . . . . . \underline{849}
\lstdrv@fortran@keys . . . . . . . . . . \underline{819}
\lstdrv@fortran@PrePL . . . . . 847, \underline{854}
\lstdrv@fortran@TestComment . . . . \underline{854}

\lstdrv@java@ . . . . . . . . . . . . . . . . \underline{869} \lstdrv@lisp@ . . . . . . . . . . . . . . . . \underline{888} \lstdrv@logo@ . . . . . . . . . . . . . . . . \underline{940} \lstdrv@matlab@ . . . . . . . . . . . . . . \underline{973}

\lstdrv@matlab@keys . . . . . . . . . . . \underline{973}

\lstdrv@modula@ . . . . . . . . . . . . . \underline{1054} \lstdrv@oberon@ . . . . . . . . . . . . . \underline{1074} \lstdrv@pascal@ …. \underline{1093}, 1114, 1127 \lstdrv@perl@ . . . . . . . . . . . . . . . \underline{1193}

\lstdrv@perl@ifPOD . . . . . . \underline{1204}, 1210
\lstdrv@perl@keys . . . . . . \underline{1164}, 1196
\lstdrv@perl@PODfalse 1205, 1206, 1217
\lstdrv@perl@PODtrue . . . . 1204, 1221
\lstdrv@perl@PrepareListing . . . \underline{1204}
\lstdrv@perl@PrePL . . . . . . 1202, \underline{1207}
\lstdrv@perl@ReplaceSharp 1231, 1234
\lstdrv@perl@TestComment . . . . . . \underline{1207}
\lstdrv@perl@TestCommentCut . . . \underline{1207}
\lstdrv@perl@TestSharp . . . . . . . \underline{1207}

\lstdrv@pli@ . . . . . . . . . . . . . . . . \underline{1237}

\lstdrv@pli@keys . . . . . . . . . . . . \underline{1237}

\lstdrv@pxsc@ . . . . . . . . . . . . . . . \underline{1111} \lstdrv@simula@ \underline{1266}, 1283, 1284, 1286

\lstdrv@simula@67 . . . . . . . . . . . \underline{1283}
\lstdrv@simula@AppendOther 1301, 1337
\lstdrv@simula@AppendOther@ . . . \underline{1291}
\lstdrv@simula@cii . . . . . . . . . . . \underline{1283}
\lstdrv@simula@closingcomment . .

. . . . . . . . . 591, 1296, 1316, 1331

\lstdrv@simula@commentfalse . . . .

. . . . . . . . 1294, 1298, 1321, 1339

\lstdrv@simula@commenttrue . . . . .

. . . . . . . . . . . . . 589, 1292, 1329

\lstdrv@simula@dec . . . . . . . . . . . \underline{1283}
\lstdrv@simula@ibm . . . . . . . . . . . \underline{1283}
\lstdrv@simula@ifcomment . . . . . . .

…. 1293, 1295, 1305, 1315, 1338

\lstdrv@simula@Output@ . . . . . . . \underline{1291}
\lstdrv@simula@OutputOther . . . . \underline{1291}
\lstdrv@simula@PrepareListing . \underline{1291}

\lstdrv@sql@ . . . . . . . . . . . . . . . . \underline{1345} \lstdrv@tex@ . . . . . . . . . . . . . . . . \underline{1545}

\lstdrv@tex@allatex . . . . . . . . . . 1569
\lstdrv@tex@commoncs . . . . \underline{1376}, 1547
\lstdrv@tex@CSOrNot . . . . . . . . . . \underline{1603}
\lstdrv@tex@latex . . . . . . . . . . . 1567
\lstdrv@tex@latexcs . \underline{1376}, 1568, 1573
\lstdrv@tex@Output . . . . . . 1599, \underline{1603}
\lstdrv@tex@plain . . . . . . . . . . . 1565
\lstdrv@tex@PrepareListing . . . . \underline{1598}
\lstdrv@tex@primitive . . . . . . . . 1566
\lstdrv@tex@primitives . . . . . . . .

…. \underline{1376}, 1547, 1566, 1568, 1573 \lstdrv@tp@ . . . . . . . . . . . . . . . . . \underline{1124} \lstenv@Process . . . . . . . . . . 240, \underline{241}

\lstenv@ReadAndProcess 237, \underline{240}, 244
\lstenv@SkipLineAndProcess . 230, \underline{231}
\lstenv@TestOptional . . . . . . 237, \underline{238}

\lstlineskip . . . . . . . . . . . 7, \underline{142}, 471

M

\morekeywords . . . . . . . 8, \underline{149}, 640,

649, 723, 1115, 1128, 1285, 1287 \moretexcs . . . . . . . . . . . . . . . . . \underline{1543}

N

\newtoks . . . . . . . . . . . . . . . . . . . . 14 \normallisting . . . . . . . . . 7, \underline{171}, 468

P \PackageError . . . . . . . . . . . . . . . .

. 122, 125, 139, 143, 146, 159, 196 \PackageWarning . . . . . . . . . . . . . . 286 \postlisting . . . . . . . . . . . 7, \underline{149}, 174 \prelisting . . . . . . . . . . . . 7, \underline{149}, 174 \ProcessOptions . . . . . . . . . . . . . . 473

S \selectlisting . . . . . . . . . . . . . . .

. . . . . 3, \underline{119}, 472, 636, 1112, 1125

                                       \sensitivefalse . . . . . . . . . . . . . .

… 8, \underline{163}, 499, 520, 712, 744, 842, 964, 1102, 1257, 1276, 1367

\sensitivetrue . . . . . . . . . . . . . 8, \underline{163}, 479, 613, 765, 810, 879, 931, 1045, 1065, 1084, 1197, 1558

\spreadlisting . . . . . . . . . 7, \underline{149}, 175

\stringizer . . 8, \underline{149}, 482, 502, 523,

616, 715, 747, 768, 813, 845, 882, 934, 967, 1048, 1068, 1087, 1105, 1200, 1260, 1279, 1370, 1561

\stringstyle . . . . . . . . . . . 6, \underline{134}, 173

T \tablength . . . . . . . . . . . . 6, \underline{142}, 470 \texcs … \underline{1543}, 1547, 1566, 1568, 1573 \textunderscore . . . . . . . . . . . . . . 412

                                       \textvisiblespace . . . . . . . . . . . . 417

U \uppercase . . . . . . . 101, 105, 114, 118

Z \zap@space . . . . . 154, 156, 1543, 1544