doc-src/rail.sty
author wenzelm
Mon, 27 Mar 2000 18:08:57 +0200
changeset 8591 9d660fc42916
parent 3097 ae362c99a635
child 13044 c049910774cb
permissions -rw-r--r--
fixed \rail@tokenfont (ever used?);
     1 % rail.sty - style file to support railroad diagrams
     2 %
     3 % 09-Jul-90 L. Rooijakkers
     4 % 08-Oct-90 L. Rooijakkers      fixed centering bug when \rail@tmpc<0.
     5 % 07-Feb-91 L. Rooijakkers      added \railoptions command, indexing
     6 % 08-Feb-91 L. Rooijakkers      minor fixes
     7 % 28-Jun-94 K. Barthelmann      turned into LaTeX2e package
     8 % 08-Dec-96 K. Barthelmann      replaced \@writefile
     9 % 13-Dec-96 K. Barthelmann      cleanup
    10 %
    11 % This style file needs to be used in conjunction with the 'rail'
    12 % program. Running LaTeX as 'latex file' produces file.rai, which should be
    13 % processed by Rail with 'rail file'. This produces file.rao, which will
    14 % be picked up by LaTeX on the next 'latex file' run.
    15 %
    16 % LaTeX will warn if there is no file.rao or it's out of date.
    17 %
    18 % The macros in this file thus consist of two parts: those that read and
    19 % write the .rai and .rao files, and those that do the actual formatting
    20 % of the railroad diagrams.
    21 
    22 \NeedsTeXFormat{LaTeX2e}
    23 \ProvidesPackage{rail}[1996/12/13]
    24 
    25 % railroad diagram formatting parameters (user level)
    26 % all of these are copied into their internal versions by \railinit
    27 %
    28 % \railunit : \unitlength within railroad diagrams
    29 % \railextra : extra length at outside of diagram
    30 % \railboxheight : height of ovals and frames
    31 % \railboxskip : vertical space between lines
    32 % \railboxleft : space to the left of a box
    33 % \railboxright : space to the right of a box
    34 % \railovalspace : extra space around contents of oval
    35 % \railframespace : extra space around contents of frame
    36 % \railtextleft : space to the left of text
    37 % \railtextright : space to the right of text
    38 % \railtextup : space to lift text up
    39 % \railjoinsize : circle size of join/split arcs
    40 % \railjoinadjust : space to adjust join
    41 %
    42 % \railnamesep : separator between name and rule body
    43 
    44 \newlength\railunit
    45 \newlength\railextra
    46 \newlength\railboxheight
    47 \newlength\railboxskip
    48 \newlength\railboxleft
    49 \newlength\railboxright
    50 \newlength\railovalspace
    51 \newlength\railframespace
    52 \newlength\railtextleft
    53 \newlength\railtextright
    54 \newlength\railtextup
    55 \newlength\railjoinsize
    56 \newlength\railjoinadjust
    57 \newlength\railnamesep
    58 
    59 % initialize the parameters
    60 
    61 \setlength\railunit{1sp}
    62 \setlength\railextra{4ex}
    63 \setlength\railboxleft{1ex}
    64 \setlength\railboxright{1ex}
    65 \setlength\railovalspace{2ex}
    66 \setlength\railframespace{2ex}
    67 \setlength\railtextleft{1ex}
    68 \setlength\railtextright{1ex}
    69 \setlength\railjoinadjust{0pt}
    70 \setlength\railnamesep{1ex}
    71 
    72 \DeclareOption{10pt}{
    73   \setlength\railboxheight{16pt}
    74   \setlength\railboxskip{24pt}
    75   \setlength\railtextup{5pt}
    76   \setlength\railjoinsize{16pt}
    77 }
    78 \DeclareOption{11pt}{
    79   \setlength\railboxheight{16pt}
    80   \setlength\railboxskip{24pt}
    81   \setlength\railtextup{5pt}
    82   \setlength\railjoinsize{16pt}
    83 }
    84 \DeclareOption{12pt}{
    85   \setlength\railboxheight{20pt}
    86   \setlength\railboxskip{28pt}
    87   \setlength\railtextup{6pt}
    88   \setlength\railjoinsize{20pt}
    89 }
    90 
    91 \ExecuteOptions{10pt}
    92 \ProcessOptions
    93 
    94 % internal versions of the formatting parameters
    95 %
    96 % \rail@extra   : \railextra
    97 % \rail@boxht   : \railboxheight
    98 % \rail@boxsp   : \railboxskip
    99 % \rail@boxlf   : \railboxleft
   100 % \rail@boxrt   : \railboxright
   101 % \rail@boxhht  : \railboxheight / 2
   102 % \rail@ovalsp  : \railovalspace
   103 % \rail@framesp : \railframespace
   104 % \rail@textlf  : \railtextleft
   105 % \rail@textrt  : \railtextright
   106 % \rail@textup  : \railtextup
   107 % \rail@joinsz  : \railjoinsize
   108 % \rail@joinhsz : \railjoinsize / 2
   109 % \rail@joinadj : \railjoinadjust
   110 %
   111 % \railinit : internalize all of the parameters.
   112 
   113 \newcount\rail@extra
   114 \newcount\rail@boxht
   115 \newcount\rail@boxsp
   116 \newcount\rail@boxlf
   117 \newcount\rail@boxrt
   118 \newcount\rail@boxhht
   119 \newcount\rail@ovalsp
   120 \newcount\rail@framesp
   121 \newcount\rail@textlf
   122 \newcount\rail@textrt
   123 \newcount\rail@textup
   124 \newcount\rail@joinsz
   125 \newcount\rail@joinhsz
   126 \newcount\rail@joinadj
   127 
   128 \newcommand\railinit{
   129 \rail@extra=\railextra
   130 \divide\rail@extra by \railunit
   131 \rail@boxht=\railboxheight
   132 \divide\rail@boxht by \railunit
   133 \rail@boxsp=\railboxskip
   134 \divide\rail@boxsp by \railunit
   135 \rail@boxlf=\railboxleft
   136 \divide\rail@boxlf by \railunit
   137 \rail@boxrt=\railboxright
   138 \divide\rail@boxrt by \railunit
   139 \rail@boxhht=\railboxheight
   140 \divide\rail@boxhht by \railunit
   141 \divide\rail@boxhht by 2
   142 \rail@ovalsp=\railovalspace
   143 \divide\rail@ovalsp by \railunit
   144 \rail@framesp=\railframespace
   145 \divide\rail@framesp by \railunit
   146 \rail@textlf=\railtextleft
   147 \divide\rail@textlf by \railunit
   148 \rail@textrt=\railtextright
   149 \divide\rail@textrt by \railunit
   150 \rail@textup=\railtextup
   151 \divide\rail@textup by \railunit
   152 \rail@joinsz=\railjoinsize
   153 \divide\rail@joinsz by \railunit
   154 \rail@joinhsz=\railjoinsize
   155 \divide\rail@joinhsz by \railunit
   156 \divide\rail@joinhsz by 2
   157 \rail@joinadj=\railjoinadjust
   158 \divide\rail@joinadj by \railunit
   159 }
   160 
   161 \AtBeginDocument{\railinit}
   162 
   163 % \rail@param : declarations for list environment
   164 %
   165 % \railparam{TEXT} : sets \rail@param to TEXT
   166 
   167 \def\rail@param{}
   168 
   169 \newcommand\railparam[1]{
   170 \def\rail@param{#1}
   171 }
   172 
   173 % \rail@tokenfont : format setup for \railtoken identifiers
   174 %
   175 % \rail@termfont : format setup for terminals
   176 %
   177 % \rail@nontfont : format setup for nonterminals
   178 %
   179 % \rail@annofont : format setup for annotations
   180 %
   181 % \rail@rulefont : format setup for rule names
   182 %
   183 % \rail@indexfont : format setup for index entry
   184 %
   185 % \railtermfont{TEXT} : set terminal format setup to TEXT
   186 %
   187 % \railnontermfont{TEXT} : set nonterminal format setup to TEXT
   188 %
   189 % \railannotatefont{TEXT} : set annotation format setup to TEXT
   190 %
   191 % \railnamefont{TEXT} : set rule name format setup to TEXT
   192 %
   193 % \railindexfont{TEXT} : set index entry format setup to TEXT
   194 
   195 \def\rail@tokenfont{\ttfamily\upshape}
   196 \def\rail@termfont{\ttfamily\upshape}
   197 \def\rail@nontfont{\rmfamily\upshape}
   198 \def\rail@annofont{\rmfamily\itshape}
   199 \def\rail@namefont{\rmfamily\itshape}
   200 \def\rail@indexfont{\rmfamily\itshape}
   201 
   202 \newcommand\railtermfont[1]{
   203 \def\rail@termfont{#1}
   204 }
   205 
   206 \newcommand\railnontermfont[1]{
   207 \def\rail@nontfont{#1}
   208 }
   209 
   210 \newcommand\railannotatefont[1]{
   211 \def\rail@annofont{#1}
   212 }
   213 
   214 \newcommand\railnamefont[1]{
   215 \def\rail@namefont{#1}
   216 }
   217 
   218 \newcommand\railindexfont[1]{
   219 \def\rail@indexfont{#1}
   220 }
   221 
   222 % railroad read/write macros
   223 %
   224 % \begin{rail} TEXT \end{rail} : TEXT is written out to the .rai file,
   225 %                                as \rail@i{NR}{TEXT}. Then the matching
   226 %                                \rail@o{NR}{FMT} from the .rao file is
   227 %                                executed (if defined).
   228 %
   229 % \railoptions{OPTIONS} : OPTIONS are written out to the .rai file,
   230 %                         as \rail@p{OPTIONS}.
   231 %
   232 % \railterm{IDENT,IDENT,...} : format IDENT as terminals. writes out
   233 %                              \rail@t{IDENT} to the .rai file
   234 %
   235 % \railalias{IDENT}{TEXT} : format IDENT as TEXT. defines \rail@t@IDENT as
   236 %                           TEXT.
   237 %
   238 % \rail@nr : railroad diagram counter
   239 %
   240 % \ifrail@match : current \rail@i{NR}{TEXT} matches
   241 %
   242 % \rail@first : actions to be done first. read in .rao file,
   243 %               open .rai file if \@filesw true, undefine \rail@first.
   244 %               executed from \begin{rail} and \railtoken.
   245 %
   246 % \rail@i{NR}{TEXT} : defines \rail@i@NR as TEXT. written to the .rai
   247 %                     file by \rail, read from the .rao file by
   248 %                     \rail@first
   249 %
   250 % \rail@t{IDENT} : tells Rail that IDENT is to be custom formatted,
   251 %                  written to the .rai file by \railterm.
   252 %
   253 % \rail@o{NR}{TEXT} : defines \rail@o@NR as TEXT, read from the .rao
   254 %                     file by \rail@first.
   255 %
   256 % \rail@p{OPTIONS} : pass options to rail, written to the .rai file by
   257 %                    \railoptions
   258 %
   259 % \rail@write{TEXT} : write TEXT to the .rai file
   260 %
   261 % \rail@warn : warn user for mismatching diagrams
   262 %
   263 % \rail@endwarn : either \relax or \rail@warn
   264 %
   265 % \ifrail@all : checked at the end of the document
   266 
   267 \newcount\rail@nr
   268 
   269 \newif\ifrail@all
   270 \rail@alltrue
   271 
   272 \newif\ifrail@match
   273 
   274 \def\rail@first{
   275 \makeatletter
   276 \InputIfFileExists{\jobname.rao}{}{\PackageInfo{rail}{No file \jobname.rao}}
   277 \makeatother
   278 \if@filesw
   279 \newwrite\tf@rai
   280 \immediate\openout\tf@rai=\jobname.rai
   281 \fi
   282 \global\let\rail@first=\relax
   283 }
   284 
   285 \long\def\rail@body#1\end{
   286 \begingroup
   287 \let\\=\relax
   288 \xdef\rail@i@{#1}
   289 \rail@write{\string\rail@i{\number\rail@nr}{\rail@i@}}
   290 \endgroup
   291 \end
   292 }
   293 
   294 \newenvironment{rail}{
   295 \global\advance\rail@nr by 1
   296 \rail@first
   297 \rail@body
   298 }{
   299 \rail@matchtrue
   300 \@ifundefined{rail@o@\number\rail@nr}{\rail@matchfalse}{}
   301 \expandafter\ifx\csname rail@i@\number\rail@nr\endcsname\rail@i@
   302 \else
   303 \rail@matchfalse
   304 \fi
   305 \ifrail@match
   306 \csname rail@o@\number\rail@nr\endcsname
   307 \else
   308 \PackageWarning{rail}{Railroad diagram {\number\rail@nr} doesn't match}
   309 \global\let\rail@endwarn=\rail@warn
   310 \begin{list}{}{\rail@param}
   311 \rail@begin{1}{}
   312 \rail@setbox{\bfseries ???}
   313 \rail@oval
   314 \rail@end
   315 \end{list}
   316 \fi
   317 }
   318 
   319 \newcommand\railoptions[1]{
   320 \rail@first
   321 \rail@write{\string\rail@p{#1}}
   322 }
   323 
   324 \newcommand\railterm[1]{
   325 \rail@first
   326 \@for\rail@@:=#1\do{
   327 \rail@write{\string\rail@t{\rail@@}}
   328 }
   329 }
   330 
   331 \newcommand\railalias[2]{
   332 \expandafter\def\csname rail@t@#1\endcsname{#2}
   333 }
   334 
   335 \long\def\rail@i#1#2{
   336 \expandafter\gdef\csname rail@i@#1\endcsname{#2}
   337 }
   338 
   339 \def\rail@o#1#2{
   340 \expandafter\gdef\csname rail@o@#1\endcsname{
   341 \begin{list}{}{\rail@param}#2\end{list}
   342 }
   343 }
   344 
   345 \def\rail@t#1{}
   346 
   347 \def\rail@p#1{}
   348 
   349 \def\rail@write#1{\@ifundefined{tf@rai}{}{\immediate\write\tf@rai{#1}}}
   350 
   351 \def\rail@warn{
   352 \PackageWarningNoLine{rail}{Railroad diagram(s) may have changed.
   353                             Use 'rail' and rerun}
   354 }
   355 
   356 \let\rail@endwarn=\relax
   357 
   358 \AtEndDocument{\rail@endwarn}
   359 
   360 % index entry macro
   361 %
   362 % \rail@index{IDENT} : add index entry for IDENT
   363 
   364 \def\rail@index#1{
   365 \index{\rail@indexfont#1}
   366 }
   367 
   368 % railroad formatting primitives
   369 %
   370 % \rail@x : current x
   371 % \rail@y : current y
   372 % \rail@ex : current end x
   373 % \rail@sx : starting x for \rail@cr
   374 % \rail@rx : rightmost previous x for \rail@cr
   375 %
   376 % \rail@tmpa : temporary count
   377 % \rail@tmpb : temporary count
   378 % \rail@tmpc : temporary count
   379 %
   380 % \rail@put : put at (\rail@x,\rail@y)
   381 %
   382 % \rail@eline : end line by drawing from \rail@ex to \rail@x
   383 %
   384 % \rail@sety{LEVEL} : set \rail@y to level LEVEL
   385 
   386 \newcount\rail@x
   387 \newcount\rail@y
   388 \newcount\rail@ex
   389 \newcount\rail@sx
   390 \newcount\rail@rx
   391 
   392 \newcount\rail@tmpa
   393 \newcount\rail@tmpb
   394 \newcount\rail@tmpc
   395 
   396 \def\rail@put{\put(\number\rail@x,\number\rail@y)}
   397 
   398 \def\rail@eline{
   399 \rail@tmpb=\rail@x
   400 \advance\rail@tmpb by -\rail@ex
   401 \rail@put{\line(-1,0){\number\rail@tmpb}}
   402 }
   403 
   404 \def\rail@sety#1{
   405 \rail@y=#1
   406 \multiply\rail@y by -\rail@boxsp
   407 \advance\rail@y by -\rail@boxht
   408 }
   409 
   410 % \rail@begin{HEIGHT}{NAME} : begin a railroad diagram of height HEIGHT
   411 %
   412 % \rail@end : end a railroad diagram
   413 %
   414 % \rail@expand{IDENT} : expand IDENT
   415 
   416 \def\rail@begin#1#2{
   417 \item[]
   418 \begin{minipage}[t]{\linewidth}
   419 \ifx\@empty#2\else
   420 {\rail@namefont \rail@expand{#2}}\\*[\railnamesep]
   421 \fi
   422 \unitlength=\railunit
   423 \rail@tmpa=#1
   424 \multiply\rail@tmpa by \rail@boxsp
   425 \begin{picture}(0,\number\rail@tmpa)(0,-\number\rail@tmpa)
   426 \rail@ex=0
   427 \rail@rx=0
   428 \rail@x=\rail@extra
   429 \rail@sx=\rail@x
   430 \rail@sety{0}
   431 }
   432 
   433 \def\rail@end{
   434 \advance\rail@x by \rail@extra
   435 \rail@eline
   436 \end{picture}
   437 \end{minipage}
   438 }
   439 
   440 \def\rail@expand#1{\@ifundefined{rail@t@#1}{#1}{\csname rail@t@#1\endcsname}}
   441 
   442 % \rail@token{TEXT}[ANNOT] : format token TEXT with annotation
   443 %
   444 % \rail@ctoken{TEXT}[ANNOT] : format token TEXT centered with annotation
   445 %
   446 % \rail@nont{TEXT}[ANNOT] : format nonterminal TEXT with annotation
   447 %
   448 % \rail@cnont{TEXT}[ANNOT] : format nonterminal TEXT centered with annotation
   449 %
   450 % \rail@term{TEXT}[ANNOT] : format terminal TEXT with annotation
   451 %
   452 % \rail@cterm{TEXT}[ANNOT] : format terminal TEXT centered with annotation
   453 %
   454 % \rail@annote[TEXT] : format TEXT as annotation
   455 
   456 \def\rail@token#1[#2]{
   457 \rail@setbox{%
   458 {\rail@tokenfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   459 }
   460 \rail@oval
   461 }
   462 
   463 \def\rail@ctoken#1[#2]{
   464 \rail@setbox{%
   465 {\rail@tokenfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   466 }
   467 \rail@coval
   468 }
   469 
   470 \def\rail@nont#1[#2]{
   471 \rail@setbox{%
   472 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   473 }
   474 \rail@frame
   475 }
   476 
   477 \def\rail@cnont#1[#2]{
   478 \rail@setbox{%
   479 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   480 }
   481 \rail@cframe
   482 }
   483 
   484 \def\rail@term#1[#2]{
   485 \rail@setbox{%
   486 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   487 }
   488 \rail@oval
   489 }
   490 
   491 \def\rail@cterm#1[#2]{
   492 \rail@setbox{%
   493 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   494 }
   495 \rail@coval
   496 }
   497 
   498 \def\rail@annote[#1]{
   499 \rail@setbox{\rail@annofont #1}
   500 \rail@text
   501 }
   502 
   503 % \rail@box : temporary box for \rail@oval and \rail@frame
   504 %
   505 % \rail@setbox{TEXT} : set \rail@box to TEXT, set \rail@tmpa to width
   506 %
   507 % \rail@oval : format \rail@box of width \rail@tmpa inside an oval
   508 %
   509 % \rail@coval : same as \rail@oval, but centered between \rail@x and
   510 %               \rail@mx
   511 %
   512 % \rail@frame : format \rail@box of width \rail@tmpa inside a frame
   513 %
   514 % \rail@cframe : same as \rail@frame, but centered between \rail@x and
   515 %                \rail@mx
   516 %
   517 % \rail@text : format \rail@box of width \rail@tmpa above the line
   518 
   519 \newbox\rail@box
   520 
   521 \def\rail@setbox#1{
   522 \setbox\rail@box\hbox{\strut#1}
   523 \rail@tmpa=\wd\rail@box
   524 \divide\rail@tmpa by \railunit
   525 }
   526 
   527 \def\rail@oval{
   528 \advance\rail@x by \rail@boxlf
   529 \rail@eline
   530 \advance\rail@tmpa by \rail@ovalsp
   531 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
   532 \rail@tmpb=\rail@tmpa
   533 \divide\rail@tmpb by 2
   534 \advance\rail@y by -\rail@boxhht
   535 \rail@put{\makebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
   536 \advance\rail@y by \rail@boxhht
   537 \advance\rail@x by \rail@tmpb
   538 \rail@put{\oval(\number\rail@tmpa,\number\rail@boxht)}
   539 \advance\rail@x by \rail@tmpb
   540 \rail@ex=\rail@x
   541 \advance\rail@x by \rail@boxrt
   542 }
   543 
   544 \def\rail@coval{
   545 \rail@tmpb=\rail@tmpa
   546 \advance\rail@tmpb by \rail@ovalsp
   547 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
   548 \advance\rail@tmpb by \rail@boxlf
   549 \advance\rail@tmpb by \rail@boxrt
   550 \rail@tmpc=\rail@mx
   551 \advance\rail@tmpc by -\rail@x
   552 \advance\rail@tmpc by -\rail@tmpb
   553 \divide\rail@tmpc by 2
   554 \ifnum\rail@tmpc>0
   555 \advance\rail@x by \rail@tmpc
   556 \fi
   557 \rail@oval
   558 }
   559 
   560 \def\rail@frame{
   561 \advance\rail@x by \rail@boxlf
   562 \rail@eline
   563 \advance\rail@tmpa by \rail@framesp
   564 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
   565 \advance\rail@y by -\rail@boxhht
   566 \rail@put{\framebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
   567 \advance\rail@y by \rail@boxhht
   568 \advance\rail@x by \rail@tmpa
   569 \rail@ex=\rail@x
   570 \advance\rail@x by \rail@boxrt
   571 }
   572 
   573 \def\rail@cframe{
   574 \rail@tmpb=\rail@tmpa
   575 \advance\rail@tmpb by \rail@framesp
   576 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
   577 \advance\rail@tmpb by \rail@boxlf
   578 \advance\rail@tmpb by \rail@boxrt
   579 \rail@tmpc=\rail@mx
   580 \advance\rail@tmpc by -\rail@x
   581 \advance\rail@tmpc by -\rail@tmpb
   582 \divide\rail@tmpc by 2
   583 \ifnum\rail@tmpc>0
   584 \advance\rail@x by \rail@tmpc
   585 \fi
   586 \rail@frame
   587 }
   588 
   589 \def\rail@text{
   590 \advance\rail@x by \rail@textlf
   591 \advance\rail@y by \rail@textup
   592 \rail@put{\box\rail@box}
   593 \advance\rail@y by -\rail@textup
   594 \advance\rail@x by \rail@tmpa
   595 \advance\rail@x by \rail@textrt
   596 }
   597 
   598 % alternatives
   599 %
   600 % \rail@jx \rail@jy : current join point
   601 %
   602 % \rail@gx \rail@gy \rail@gex \rail@grx : global versions of \rail@x etc,
   603 %                                         to pass values over group closings
   604 %
   605 % \rail@mx : maximum x so far
   606 %
   607 % \rail@sy : starting \rail@y for alternatives
   608 %
   609 % \rail@jput : put at (\rail@jx,\rail@jy)
   610 %
   611 % \rail@joval[PART] : put \oval[PART] with adjust
   612 
   613 \newcount\rail@jx
   614 \newcount\rail@jy
   615 
   616 \newcount\rail@gx
   617 \newcount\rail@gy
   618 \newcount\rail@gex
   619 \newcount\rail@grx
   620 
   621 \newcount\rail@sy
   622 \newcount\rail@mx
   623 
   624 \def\rail@jput{
   625 \put(\number\rail@jx,\number\rail@jy)
   626 }
   627 
   628 \def\rail@joval[#1]{
   629 \advance\rail@jx by \rail@joinadj
   630 \rail@jput{\oval(\number\rail@joinsz,\number\rail@joinsz)[#1]}
   631 \advance\rail@jx by -\rail@joinadj
   632 }
   633 
   634 % \rail@barsplit : incoming split for '|'
   635 %
   636 % \rail@plussplit : incoming split for '+'
   637 %
   638 
   639 \def\rail@barsplit{
   640 \advance\rail@jy by -\rail@joinhsz
   641 \rail@joval[tr]
   642 \advance\rail@jx by \rail@joinhsz
   643 }
   644 
   645 \def\rail@plussplit{
   646 \advance\rail@jy by -\rail@joinhsz
   647 \advance\rail@jx by \rail@joinsz
   648 \rail@joval[tl]
   649 \advance\rail@jx by -\rail@joinhsz
   650 }
   651 
   652 % \rail@alt{SPLIT} : start alternatives with incoming split SPLIT
   653 %
   654 
   655 \def\rail@alt#1{
   656 \rail@sy=\rail@y
   657 \rail@jx=\rail@x
   658 \rail@jy=\rail@y
   659 \advance\rail@x by \rail@joinsz
   660 \rail@mx=0
   661 \let\rail@list=\@empty
   662 \let\rail@comma=\@empty
   663 \let\rail@split=#1
   664 \begingroup
   665 \rail@sx=\rail@x
   666 \rail@rx=0
   667 }
   668 
   669 % \rail@nextalt{FIX}{Y} : start next alternative at vertical position Y
   670 %                         and fix-up FIX
   671 %
   672 
   673 \def\rail@nextalt#1#2{
   674 \global\rail@gx=\rail@x
   675 \global\rail@gy=\rail@y
   676 \global\rail@gex=\rail@ex
   677 \global\rail@grx=\rail@rx
   678 \endgroup
   679 #1
   680 \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
   681 \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
   682 \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
   683 \def\rail@comma{,}
   684 \rail@split
   685 \let\rail@split=\@empty
   686 \rail@sety{#2}
   687 \rail@tmpa=\rail@jy
   688 \advance\rail@tmpa by -\rail@y
   689 \advance\rail@tmpa by -\rail@joinhsz
   690 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   691 \rail@jy=\rail@y
   692 \advance\rail@jy by \rail@joinhsz
   693 \advance\rail@jx by \rail@joinhsz
   694 \rail@joval[bl]
   695 \advance\rail@jx by -\rail@joinhsz
   696 \rail@ex=\rail@x
   697 \begingroup
   698 \rail@sx=\rail@x
   699 \rail@rx=0
   700 }
   701 
   702 % \rail@barjoin : outgoing join for first '|' alternative
   703 %
   704 % \rail@plusjoin : outgoing join for first '+' alternative
   705 %
   706 % \rail@altjoin : join for subsequent alternative
   707 %
   708 
   709 \def\rail@barjoin{
   710 \ifnum\rail@y<\rail@sy
   711 \global\rail@gex=\rail@jx
   712 \else
   713 \global\rail@gex=\rail@ex
   714 \fi
   715 \advance\rail@jy by -\rail@joinhsz
   716 \rail@joval[tl]
   717 \advance\rail@jx by -\rail@joinhsz
   718 \ifnum\rail@y<\rail@sy
   719 \rail@altjoin
   720 \fi
   721 }
   722 
   723 \def\rail@plusjoin{
   724 \global\rail@gex=\rail@ex
   725 \advance\rail@jy by -\rail@joinhsz
   726 \advance\rail@jx by -\rail@joinsz
   727 \rail@joval[tr]
   728 \advance\rail@jx by \rail@joinhsz
   729 }
   730 
   731 \def\rail@altjoin{
   732 \rail@eline
   733 \rail@tmpa=\rail@jy
   734 \advance\rail@tmpa by -\rail@y
   735 \advance\rail@tmpa by -\rail@joinhsz
   736 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   737 \rail@jy=\rail@y
   738 \advance\rail@jy by \rail@joinhsz
   739 \advance\rail@jx by -\rail@joinhsz
   740 \rail@joval[br]
   741 \advance\rail@jx by \rail@joinhsz
   742 }
   743 
   744 % \rail@eltsplit EX:Y; : split EX:Y into \rail@ex \rail@y
   745 %
   746 % \rail@endalt{JOIN} : end alternatives with outgoing join JOIN
   747 
   748 \def\rail@eltsplit#1:#2;{\rail@ex=#1\rail@y=#2}
   749 
   750 \def\rail@endalt#1{
   751 \global\rail@gx=\rail@x
   752 \global\rail@gy=\rail@y
   753 \global\rail@gex=\rail@ex
   754 \global\rail@grx=\rail@rx
   755 \endgroup
   756 \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
   757 \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
   758 \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
   759 \rail@x=\rail@mx
   760 \rail@jx=\rail@x
   761 \rail@jy=\rail@sy
   762 \advance\rail@jx by \rail@joinsz
   763 \let\rail@join=#1
   764 \@for\rail@elt:=\rail@list\do{
   765 \expandafter\rail@eltsplit\rail@elt;
   766 \rail@join
   767 \let\rail@join=\rail@altjoin
   768 }
   769 \rail@x=\rail@mx
   770 \rail@y=\rail@sy
   771 \rail@ex=\rail@gex
   772 \advance\rail@x by \rail@joinsz
   773 }
   774 
   775 % \rail@bar : start '|' alternatives
   776 %
   777 % \rail@nextbar : next '|' alternative
   778 %
   779 % \rail@endbar : end '|' alternatives
   780 %
   781 
   782 \def\rail@bar{
   783 \rail@alt\rail@barsplit
   784 }
   785 
   786 \def\rail@nextbar{
   787 \rail@nextalt\relax
   788 }
   789 
   790 \def\rail@endbar{
   791 \rail@endalt\rail@barjoin
   792 }
   793 
   794 % \rail@plus : start '+' alternatives
   795 %
   796 % \rail@nextplus: next '+' alternative
   797 %
   798 % \rail@endplus : end '+' alternatives
   799 %
   800 
   801 \def\rail@plus{
   802 \rail@alt\rail@plussplit
   803 }
   804 
   805 \def\rail@nextplus{
   806 \rail@nextalt\rail@fixplus
   807 }
   808 
   809 \def\rail@fixplus{
   810 \ifnum\rail@gy<\rail@sy
   811 \begingroup
   812 \rail@x=\rail@gx
   813 \rail@y=\rail@gy
   814 \rail@ex=\rail@gex
   815 \rail@rx=\rail@grx
   816 \ifnum\rail@x<\rail@rx
   817 \rail@x=\rail@rx
   818 \fi
   819 \rail@eline
   820 \rail@jx=\rail@x
   821 \rail@jy=\rail@y
   822 \advance\rail@jy by \rail@joinhsz
   823 \rail@joval[br]
   824 \advance\rail@jx by \rail@joinhsz
   825 \rail@tmpa=\rail@sy
   826 \advance\rail@tmpa by -\rail@joinhsz
   827 \advance\rail@tmpa by -\rail@jy
   828 \rail@jput{\line(0,1){\number\rail@tmpa}}
   829 \rail@jy=\rail@sy
   830 \advance\rail@jy by -\rail@joinhsz
   831 \advance\rail@jx by \rail@joinhsz
   832 \rail@joval[tl]
   833 \advance\rail@jy by \rail@joinhsz
   834 \global\rail@gx=\rail@jx
   835 \global\rail@gy=\rail@jy
   836 \global\rail@gex=\rail@gx
   837 \global\rail@grx=\rail@rx
   838 \endgroup
   839 \fi
   840 }
   841 
   842 \def\rail@endplus{
   843 \rail@endalt\rail@plusjoin
   844 }
   845 
   846 % \rail@cr{Y} : carriage return to vertical position Y
   847 
   848 \def\rail@cr#1{
   849 \rail@tmpa=\rail@sx
   850 \advance\rail@tmpa by \rail@joinsz
   851 \ifnum\rail@x<\rail@tmpa\rail@x=\rail@tmpa\fi
   852 \rail@eline
   853 \rail@jx=\rail@x
   854 \rail@jy=\rail@y
   855 \advance\rail@x by \rail@joinsz
   856 \ifnum\rail@x>\rail@rx\rail@rx=\rail@x\fi
   857 \advance\rail@jy by -\rail@joinhsz
   858 \rail@joval[tr]
   859 \advance\rail@jx by \rail@joinhsz
   860 \rail@sety{#1}
   861 \rail@tmpa=\rail@jy
   862 \advance\rail@tmpa by -\rail@y
   863 \advance\rail@tmpa by -\rail@boxsp
   864 \advance\rail@tmpa by -\rail@joinhsz
   865 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   866 \rail@jy=\rail@y
   867 \advance\rail@jy by \rail@boxsp
   868 \advance\rail@jy by \rail@joinhsz
   869 \advance\rail@jx by -\rail@joinhsz
   870 \rail@joval[br]
   871 \advance\rail@jy by -\rail@joinhsz
   872 \rail@tmpa=\rail@jx
   873 \advance\rail@tmpa by -\rail@sx
   874 \advance\rail@tmpa by -\rail@joinhsz
   875 \rail@jput{\line(-1,0){\number\rail@tmpa}}
   876 \rail@jx=\rail@sx
   877 \advance\rail@jx by \rail@joinhsz
   878 \advance\rail@jy by -\rail@joinhsz
   879 \rail@joval[tl]
   880 \advance\rail@jx by -\rail@joinhsz
   881 \rail@tmpa=\rail@boxsp
   882 \advance\rail@tmpa by -\rail@joinsz
   883 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   884 \advance\rail@jy by -\rail@tmpa
   885 \advance\rail@jx by \rail@joinhsz
   886 \rail@joval[bl]
   887 \rail@x=\rail@jx
   888 \rail@ex=\rail@x
   889 }