dialect. Thanks to Walter E. Brown for reporting a problem with the argument delimiter ‘[’ in a previous definition of\lstalias@.
2378\lst@UserCommand\lstalias{\@ifnextchar[\lstalias@\lstalias@@}
2379\gdef\lstalias@[#1]#2{\lstalias@b #2$#1}
2380\gdef\lstalias@b#1[#2]#3{\lst@NormedNameDef{lsta@#1}{#3$#2}}
2381\gdef\lstalias@@#1#2{\lst@NormedNameDef{lsta@#1}{#2}}
defaultdialect We simply store the dialect.
2382\lst@Key{defaultdialect}\relax
2383 {\lstKV@OptArg[]{#1}{\lst@NormedNameDef{lstdd@##2}{##1}}}
\lst@FindAlias Now we have to find a language. First we test for a complete language alias, then we set the default dialect if necessary.
2384\gdef\lst@FindAlias[#1]#2{%
2385 \lst@NormedDef\lst@oalias{#1}%
2386 \lst@NormedDef\lst@malias{#2}%
2387 \@ifundefined{lsta@\lst@malias}{}%
2388 {\edef\lst@malias{\csname\@lst a@\lst@malias\endcsname}}%
2389 \ifx\@empty\lst@oalias \@ifundefined{lstdd@\lst@malias}{}%
2390 {\edef\lst@oalias{\csname\@lst dd@\lst@malias\endcsname}}%
2391 \fi
Now we are ready for an alias of a single dialect.
2392 \edef\lst@temp{\lst@malias $\lst@oalias}%
2393 \@ifundefined{lsta@\lst@temp}{}%
2394 {\edef\lst@temp{\csname\@lst a@\lst@temp\endcsname}}%
Finally we again set the default dialect—for the case of a dialect alias.
2395 \expandafter\lst@FindAlias@\lst@temp $}
2396\gdef\lst@FindAlias@#1$#2${%
2397 \def\lst@malias{#1}\def\lst@oalias{#2}%
2398 \ifx\@empty\lst@oalias \@ifundefined{lstdd@\lst@malias}{}%
2399 {\edef\lst@oalias{\csname\@lst dd@\lst@malias\endcsname}}%
2400 \fi}
\lst@RequireLanguages This definition will be equivalent to\lstloadlanguages. We requested the given list of languages and load additionally required aspects.
2401\gdef\lst@RequireLanguages#1{%
2402 \lst@Require{language}{lang}{#1}\lst@FindAlias\lstlanguagefiles
2403 \ifx\lst@loadaspects\@empty\else
2404 \lst@RequireAspects\lst@loadaspects
2405 \fi}
\lstloadlanguages is the same as\lst@RequireLanguages.
2406\global\let\lstloadlanguages\lst@RequireLanguages
2407\lst@EndAspect
2408h/misci
\lstformatfiles This macro is defined if and only if it’s undefined yet.
2411\@ifundefined{lstformatfiles}
2412 {\lst@UserCommand\lstformatfiles{lstfmt0.sty}}{}
\lstdefineformat
\lst@defineformat
\lst@DefFormat
are defined in terms of\lst@DefFormat, which is defined via\lst@DefDriver.
2413\lst@UserCommand\lstdefineformat{\lst@DefFormat\iftrue}
2414\lst@UserCommand\lst@defineformat{\lst@DefFormat\iffalse}
2415\gdef\lst@DefFormat{\lst@DefDriver{format}{fmt}\lst@UseFormat}
We provide the ‘empty’ format.
2416\lstdefineformat{}{}
format is an application of \lst@LAS. We just specify the hook as ‘pre’ and an empty argument as ‘post’ code.
2417\lst@Key{format}\relax{%
2418 \lst@LAS{format}{fmt}{[]{#1}}\lst@NoAlias\lstformatfiles
2419 \lsthk@SetFormat
2420 {}}
2421\lst@AddToHook{SetFormat}{\let\lst@fmtformat\@empty}% init
Helpers Our goal is to define the yet unkown\lst@UseFormat. This definition will parse the user supplied format. We start with some general macros.
\lst@fmtSplit splits the content of the macro#1at#2in the preceding characters\lst@fmtaand the following ones \lst@fmtb. \lst@if is false if and only if#1doesn’t contain
#2.
2422\gdef\lst@fmtSplit#1#2{%
2423 \def\lst@temp##1#2##2\relax##3{%
2424 \ifnum##3=\z@
2425 \ifx\@empty##2\@empty
2426 \lst@false
2427 \let\lst@fmta#1%
2428 \let\lst@fmtb\@empty
2429 \else
2430 \expandafter\lst@temp#1\relax\@ne
2431 \fi
2432 \else
2433 \def\lst@fmta{##1}\def\lst@fmtb{##2}%
2434 \fi}%
2435 \lst@true
2436 \expandafter\lst@temp#1#2\relax\z@}
\lst@IfNextCharWhitespace is defined in terms of\lst@IfSubstring.
2437\gdef\lst@IfNextCharWhitespace#1#2#3{%
2438 \lst@IfSubstring#3\lst@whitespaces{#1}{#2}#3}
And here come all white space characters.
2439\begingroup
2440\catcode‘\^^I=12\catcode‘\^^J=12\catcode‘\^^M=12\catcode‘\^^L=12\relax%
2441\lst@DefActive\lst@whitespaces{\ ^^I^^J^^M}% add ^^L
2442\global\let\lst@whitespaces\lst@whitespaces%
2443\endgroup
\lst@fmtIfIdentifier tests the first character of#1
2444\gdef\lst@fmtIfIdentifier#1{%
2445 \ifx\relax#1\@empty
2446 \expandafter\@secondoftwo
2447 \else
2448 \expandafter\lst@fmtIfIdentifier@\expandafter#1%
2449 \fi}
against the ‘letters’_,@,A,. . . ,Zanda,. . . ,z.
2450\gdef\lst@fmtIfIdentifier@#1#2\relax{%
2451 \let\lst@next\@secondoftwo
2452 \ifnum‘#1=‘_\else
2453 \ifnum‘#1<64\else
2454 \ifnum‘#1<91\let\lst@next\@firstoftwo\else
2455 \ifnum‘#1<97\else
2456 \ifnum‘#1<123\let\lst@next\@firstoftwo\else
2457 \fi \fi \fi \fi \fi
2458 \lst@next}
\lst@fmtIfNextCharIn is required for the optionalhexceptional charactersi. The implementation is easy—
refer section 13.1.
2459\gdef\lst@fmtIfNextCharIn#1{%
2460 \ifx\@empty#1\@empty \expandafter\@secondoftwo \else
2461 \def\lst@next{\lst@fmtIfNextCharIn@{#1}}%
2462 \expandafter\lst@next\fi}
2463\gdef\lst@fmtIfNextCharIn@#1#2#3#4{%
2464 \def\lst@temp##1#4##2##3\relax{%
2465 \ifx \@empty##2\expandafter\@secondoftwo
2466 \else \expandafter\@firstoftwo \fi}%
2467 \lst@temp#1#4\@empty\relax{#2}{#3}#4}
\lst@fmtCDef We need derivations of\lst@CDefand\lst@CDefX: we have to test the next char- acter against the sequence #5of exceptional characters. These tests are inserted here.
2468\gdef\lst@fmtCDef#1{\lst@fmtCDef@#1}
2469\gdef\lst@fmtCDef@#1#2#3#4#5#6#7{%
2470 \lst@CDefIt#1{#2}{#3}%
2471 {\lst@fmtIfNextCharIn{#5}{#4#2#3}{#6#4#2#3#7}}%
2472 #4%
2473 {}{}{}}
\lst@fmtCDefX The same but ‘drop input’.
2474\gdef\lst@fmtCDefX#1{\lst@fmtCDefX@#1}
2475\gdef\lst@fmtCDefX@#1#2#3#4#5#6#7{%
2476 \let#4#1%
2477 \ifx\@empty#2\@empty
2478 \def#1{\lst@fmtIfNextCharIn{#5}{#4}{#6#7}}%
2479 \else \ifx\@empty#3\@empty
2480 \def#1##1{%
2481 \ifx##1#2%
2482 \def\lst@next{\lst@fmtIfNextCharIn{#5}{#4##1}%
2483 {#6#7}}%
2484 \else
2485 \def\lst@next{#4##1}%
2486 \fi
2487 \lst@next}%
2488 \else
2489 \def#1{%
2490 \lst@IfNextCharsArg{#2#3}%
2491 {\lst@fmtIfNextCharIn{#5}{\expandafter#4\lst@eaten}%
2492 {#6#7}}%
2493 {\expandafter#4\lst@eaten}}%
2494 \fi \fi}
The parser applies\lst@fmtSplitto cut a format definition into items, items into ‘input’ and ‘output’, and ‘output’ into ‘pre’ and ’post’. This should be clear if you are in touch with format definitions.
\lst@UseFormat Now we can start with the parser.
2495\gdef\lst@UseFormat#1{%
2496 \def\lst@fmtwhole{#1}%
2497 \lst@UseFormat@}
2498\gdef\lst@UseFormat@{%
2499 \lst@fmtSplit\lst@fmtwhole,%
We assign the rest of the format definition, . . .
2500 \let\lst@fmtwhole\lst@fmtb
2501 \ifx\lst@fmta\@empty\else
. . . split the item at the equal sign, and work on the item.
2502 \lst@fmtSplit\lst@fmta=%
2503 \ifx\@empty\lst@fmta\else
To do: Insert \let\lst@arg\@empty \expandafter\lst@XConvert\lst@fmtb\@nil
\let\lst@fmtb\lst@arg.
2504 \expandafter\lstKV@XOptArg\expandafter[\expandafter]%
2505 \expandafter{\lst@fmtb}\lst@UseFormat@b
2506 \fi
2507 \fi
Finally we process the next item if the rest is not empty.
2508 \ifx\lst@fmtwhole\@empty\else
2509 \expandafter\lst@UseFormat@
2510 \fi}
We make \lst@fmtccontain the preceding characters as a braced argument. To add more arguments, we first split the replacement tokens at the control sequence
\string.
2511\gdef\lst@UseFormat@b[#1]#2{%
2512 \def\lst@fmtc{{#1}}\lst@lExtend\lst@fmtc{\expandafter{\lst@fmta}}%
2513 \def\lst@fmtb{#2}%
2514 \lst@fmtSplit\lst@fmtb\string
We append an empty argument or\lst@fmtPrewith ‘\string-preceding’ tokens as argument. We do the same for the tokens after\string.
2515 \ifx\@empty\lst@fmta
2516 \lst@lAddTo\lst@fmtc{{}}%
2517 \else
2518 \lst@lExtend\lst@fmtc{\expandafter
2519 {\expandafter\lst@fmtPre\expandafter{\lst@fmta}}}%
2520 \fi
2521 \ifx\@empty\lst@fmtb
2522 \lst@lAddTo\lst@fmtc{{}}%
2523 \else
2524 \lst@lExtend\lst@fmtc{\expandafter
2525 {\expandafter\lst@fmtPost\expandafter{\lst@fmtb}}}%
2526 \fi
Eventually we extend \lst@fmtformat appropriately. Note that \lst@if still indicates whether the replacement tokens contain\string.
2527 \expandafter\lst@UseFormat@c\lst@fmtc}
2528\gdef\lst@UseFormat@c#1#2#3#4{%
2529 \lst@fmtIfIdentifier#2\relax
2530 {\lst@fmtIdentifier{#2}%
2531 \lst@if\else \PackageWarning{Listings}%
2532 {Cannot drop identifier in format definition}%
2533 \fi}%
2534 {\lst@if
2535 \lst@lAddTo\lst@fmtformat{\lst@CArgX#2\relax\lst@fmtCDef}%
2536 \else
2537 \lst@lAddTo\lst@fmtformat{\lst@CArgX#2\relax\lst@fmtCDefX}%
2538 \fi
2539 \lst@DefActive\lst@fmtc{#1}%
2540 \lst@lExtend\lst@fmtformat{\expandafter{\lst@fmtc}{#3}{#4}}}}
2541\lst@AddToHook{SelectCharTable}{\lst@fmtformat}
2542\global\let\lst@fmtformat\@empty The formatting
\lst@fmtPre
2543\gdef\lst@fmtPre#1{%
2544 \lst@PrintToken
2545 \begingroup
2546 \let\newline\lst@fmtEnsureNewLine
2547 \let\space\lst@fmtEnsureSpace
2548 \let\indent\lst@fmtIndent
2549 \let\noindent\lst@fmtNoindent
2550 #1%
2551 \endgroup}
\lst@fmtPost
2552\gdef\lst@fmtPost#1{%
2553 \global\let\lst@fmtPostOutput\@empty
2554 \begingroup
2555 \def\newline{\lst@AddTo\lst@fmtPostOutput\lst@fmtEnsureNewLine}%
2556 \def\space{\aftergroup\lst@fmtEnsurePostSpace}%
2557 \def\indent{\lst@AddTo\lst@fmtPostOutput\lst@fmtIndent}%
2558 \def\noindent{\lst@AddTo\lst@fmtPostOutput\lst@fmtNoindent}%
2559 \aftergroup\lst@PrintToken
2560 #1%
2561 \endgroup}
2562\lst@AddToHook{Init}{\global\let\lst@fmtPostOutput\@empty}
2563\lst@AddToHook{PostOutput}
2564 {\lst@fmtPostOutput \global\let\lst@fmtPostOutput\@empty}
\lst@fmtEnsureSpace
\lst@fmtEnsurePostSpace2565\gdef\lst@fmtEnsureSpace{%
2566 \lst@ifwhitespace\else \expandafter\lst@ProcessSpace \fi}
2567\gdef\lst@fmtEnsurePostSpace{%
2568 \lst@IfNextCharWhitespace{}{\lst@ProcessSpace}}
fmtindent
\lst@fmtIndent
\lst@fmtNoindent
2569\lst@Key{fmtindent}{20pt}{\def\lst@fmtindent{#1}}
2570\newdimen\lst@fmtcurrindent
2571\lst@AddToHook{InitVars}{\global\lst@fmtcurrindent\z@}
2572\gdef\lst@fmtIndent{\global\advance\lst@fmtcurrindent\lst@fmtindent}
2573\gdef\lst@fmtNoindent{\global\advance\lst@fmtcurrindent-\lst@fmtindent}
\lst@fmtEnsureNewLine
2574\gdef\lst@fmtEnsureNewLine{%
2575 \global\advance\lst@newlines\@ne
2576 \global\advance\lst@newlinesensured\@ne
2577 \lst@fmtignoretrue}
2578\lst@AddToAtTop\lst@DoNewLines{%
2579 \ifnum\lst@newlines>\lst@newlinesensured
2580 \global\advance\lst@newlines-\lst@newlinesensured
2581 \fi
2582 \global\lst@newlinesensured\z@}
2583\newcount\lst@newlinesensured % global
2584\lst@AddToHook{Init}{\global\lst@newlinesensured\z@}
2585\gdef\lst@fmtignoretrue{\let\lst@fmtifignore\iftrue}
2586\gdef\lst@fmtignorefalse{\let\lst@fmtifignore\iffalse}
2587\lst@AddToHook{InitVars}{\lst@fmtignorefalse}
2588\lst@AddToHook{Output}{\lst@fmtignorefalse}
\lst@fmtUseLostSpace
2589\gdef\lst@fmtUseLostSpace{%
2590 \lst@ifnewline \kern\lst@fmtcurrindent \global\lst@lostspace\z@
2591 \else
2592 \lst@OldOLS
2593 \fi}
2594\lst@AddToHook{Init}
2595 {\lst@true
2596 \ifx\lst@fmtformat\@empty \ifx\lst@fmt\@empty \lst@false \fi\fi
2597 \lst@if
2598 \let\lst@OldOLS\lst@OutputLostSpace
2599 \let\lst@OutputLostSpace\lst@fmtUseLostSpace
2600 \let\lst@ProcessSpace\lst@fmtProcessSpace
2601 \fi}
To do: This ‘lost space’ doesn’t use\lst@alloverstyleyet!
\lst@fmtProcessSpace
2602\gdef\lst@fmtProcessSpace{%
2603 \lst@ifletter
2604 \lst@Output
2605 \lst@fmtifignore\else
2606 \lst@AppendOther\lst@outputspace
2607 \fi
2608 \else \lst@ifkeepspaces
2609 \lst@AppendOther\lst@outputspace
2610 \else \ifnum\lst@newlines=\z@
2611 \lst@AppendSpecialSpace
2612 \else \ifnum\lst@length=\z@
2613 \global\advance\lst@lostspace\lst@width
2614 \global\advance\lst@pos\m@ne
2615 \else
2616 \lst@AppendSpecialSpace
2617 \fi
2618 \fi \fi \fi
2619 \lst@whitespacetrue}
Formatting identifiers
\lst@fmtIdentifier We install a (keyword) test for the ‘format identifiers’.
2620\lst@InstallTest{f}
2621 \lst@fmt@list\lst@fmt \lst@gfmt@list\lst@gfmt
2622 \lst@gfmt@wp
2623 wd
2624\gdef\lst@fmt@list{\lst@fmt\lst@gfmt}\global\let\lst@fmt\@empty
2625\gdef\lst@gfmt@list{\lst@fmt\lst@gfmt}\global\let\lst@gfmt\@empty
The working procedure expands\lst@fmt$hstringi(and defines\lst@PrintToken to do nothing).
2626\gdef\lst@gfmt@wp{%
2627 \begingroup \let\lst@UM\@empty
2628 \let\lst@PrintToken\@empty
2629 \csname\@lst @fmt$\the\lst@token\endcsname
2630 \endgroup}
This control sequence is probably defined as ‘working identifier’.
2631\gdef\lst@fmtIdentifier#1#2#3#4{%
2632 \lst@DefOther\lst@fmta{#2}\edef\lst@fmt{\lst@fmt,\lst@fmta}%
2633 \@namedef{\@lst @fmt$\lst@fmta}{#3#4}}
\lst@fmt$hidentifieriexpands to a\lst@fmtPre/\lst@fmtPostsequence defined by#2and#3.
2634\lst@EndAspect
2635h/misci