doc-src/rail.sty
author paulson
Thu Jun 05 13:22:25 1997 +0200 (1997-06-05 ago)
changeset 3403 6cc663f6d62e
parent 3097 ae362c99a635
child 8591 9d660fc42916
permissions -rw-r--r--
A slight simplification of optstring
The new "simpset" keyword in the "recdef" declaration
     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@termfont{\ttfamily\upshape}
   196 \def\rail@nontfont{\rmfamily\upshape}
   197 \def\rail@annofont{\rmfamily\itshape}
   198 \def\rail@namefont{\rmfamily\itshape}
   199 \def\rail@indexfont{\rmfamily\itshape}
   200 
   201 \newcommand\railtermfont[1]{
   202 \def\rail@termfont{#1}
   203 }
   204 
   205 \newcommand\railnontermfont[1]{
   206 \def\rail@nontfont{#1}
   207 }
   208 
   209 \newcommand\railannotatefont[1]{
   210 \def\rail@annofont{#1}
   211 }
   212 
   213 \newcommand\railnamefont[1]{
   214 \def\rail@namefont{#1}
   215 }
   216 
   217 \newcommand\railindexfont[1]{
   218 \def\rail@indexfont{#1}
   219 }
   220 
   221 % railroad read/write macros
   222 %
   223 % \begin{rail} TEXT \end{rail} : TEXT is written out to the .rai file,
   224 %                                as \rail@i{NR}{TEXT}. Then the matching
   225 %                                \rail@o{NR}{FMT} from the .rao file is
   226 %                                executed (if defined).
   227 %
   228 % \railoptions{OPTIONS} : OPTIONS are written out to the .rai file,
   229 %                         as \rail@p{OPTIONS}.
   230 %
   231 % \railterm{IDENT,IDENT,...} : format IDENT as terminals. writes out
   232 %                              \rail@t{IDENT} to the .rai file
   233 %
   234 % \railalias{IDENT}{TEXT} : format IDENT as TEXT. defines \rail@t@IDENT as
   235 %                           TEXT.
   236 %
   237 % \rail@nr : railroad diagram counter
   238 %
   239 % \ifrail@match : current \rail@i{NR}{TEXT} matches
   240 %
   241 % \rail@first :	actions to be done first. read in .rao file,
   242 %               open .rai file if \@filesw true, undefine \rail@first.
   243 %               executed from \begin{rail} and \railtoken.
   244 %
   245 % \rail@i{NR}{TEXT} : defines \rail@i@NR as TEXT. written to the .rai
   246 %                     file by \rail, read from the .rao file by
   247 %                     \rail@first
   248 %
   249 % \rail@t{IDENT} : tells Rail that IDENT is to be custom formatted,
   250 %                  written to the .rai file by \railterm.
   251 %
   252 % \rail@o{NR}{TEXT} : defines \rail@o@NR as TEXT, read from the .rao
   253 %                     file by \rail@first.
   254 %
   255 % \rail@p{OPTIONS} : pass options to rail, written to the .rai file by
   256 %                    \railoptions
   257 %
   258 % \rail@write{TEXT} : write TEXT to the .rai file
   259 %
   260 % \rail@warn : warn user for mismatching diagrams
   261 %
   262 % \rail@endwarn : either \relax or \rail@warn
   263 %
   264 % \ifrail@all : checked at the end of the document
   265 
   266 \newcount\rail@nr
   267 
   268 \newif\ifrail@all
   269 \rail@alltrue
   270 
   271 \newif\ifrail@match
   272 
   273 \def\rail@first{
   274 \makeatletter
   275 \InputIfFileExists{\jobname.rao}{}{\PackageInfo{rail}{No file \jobname.rao}}
   276 \makeatother
   277 \if@filesw
   278 \newwrite\tf@rai
   279 \immediate\openout\tf@rai=\jobname.rai
   280 \fi
   281 \global\let\rail@first=\relax
   282 }
   283 
   284 \long\def\rail@body#1\end{
   285 \begingroup
   286 \let\\=\relax
   287 \xdef\rail@i@{#1}
   288 \rail@write{\string\rail@i{\number\rail@nr}{\rail@i@}}
   289 \endgroup
   290 \end
   291 }
   292 
   293 \newenvironment{rail}{
   294 \global\advance\rail@nr by 1
   295 \rail@first
   296 \rail@body
   297 }{
   298 \rail@matchtrue
   299 \@ifundefined{rail@o@\number\rail@nr}{\rail@matchfalse}{}
   300 \expandafter\ifx\csname rail@i@\number\rail@nr\endcsname\rail@i@
   301 \else
   302 \rail@matchfalse
   303 \fi
   304 \ifrail@match
   305 \csname rail@o@\number\rail@nr\endcsname
   306 \else
   307 \PackageWarning{rail}{Railroad diagram {\number\rail@nr} doesn't match}
   308 \global\let\rail@endwarn=\rail@warn
   309 \begin{list}{}{\rail@param}
   310 \rail@begin{1}{}
   311 \rail@setbox{\bfseries ???}
   312 \rail@oval
   313 \rail@end
   314 \end{list}
   315 \fi
   316 }
   317 
   318 \newcommand\railoptions[1]{
   319 \rail@first
   320 \rail@write{\string\rail@p{#1}}
   321 }
   322 
   323 \newcommand\railterm[1]{
   324 \rail@first
   325 \@for\rail@@:=#1\do{
   326 \rail@write{\string\rail@t{\rail@@}}
   327 }
   328 }
   329 
   330 \newcommand\railalias[2]{
   331 \expandafter\def\csname rail@t@#1\endcsname{#2}
   332 }
   333 
   334 \long\def\rail@i#1#2{
   335 \expandafter\gdef\csname rail@i@#1\endcsname{#2}
   336 }
   337 
   338 \def\rail@o#1#2{
   339 \expandafter\gdef\csname rail@o@#1\endcsname{
   340 \begin{list}{}{\rail@param}#2\end{list}
   341 }
   342 }
   343 
   344 \def\rail@t#1{}
   345 
   346 \def\rail@p#1{}
   347 
   348 \def\rail@write#1{\@ifundefined{tf@rai}{}{\immediate\write\tf@rai{#1}}}
   349 
   350 \def\rail@warn{
   351 \PackageWarningNoLine{rail}{Railroad diagram(s) may have changed.
   352                             Use 'rail' and rerun}
   353 }
   354 
   355 \let\rail@endwarn=\relax
   356 
   357 \AtEndDocument{\rail@endwarn}
   358 
   359 % index entry macro
   360 %
   361 % \rail@index{IDENT} : add index entry for IDENT
   362 
   363 \def\rail@index#1{
   364 \index{\rail@indexfont#1}
   365 }
   366 
   367 % railroad formatting primitives
   368 %
   369 % \rail@x : current x
   370 % \rail@y : current y
   371 % \rail@ex : current end x
   372 % \rail@sx : starting x for \rail@cr
   373 % \rail@rx : rightmost previous x for \rail@cr
   374 %
   375 % \rail@tmpa : temporary count
   376 % \rail@tmpb : temporary count
   377 % \rail@tmpc : temporary count
   378 %
   379 % \rail@put : put at (\rail@x,\rail@y)
   380 %
   381 % \rail@eline : end line by drawing from \rail@ex to \rail@x
   382 %
   383 % \rail@sety{LEVEL} : set \rail@y to level LEVEL
   384 
   385 \newcount\rail@x
   386 \newcount\rail@y
   387 \newcount\rail@ex
   388 \newcount\rail@sx
   389 \newcount\rail@rx
   390 
   391 \newcount\rail@tmpa
   392 \newcount\rail@tmpb
   393 \newcount\rail@tmpc
   394 
   395 \def\rail@put{\put(\number\rail@x,\number\rail@y)}
   396 
   397 \def\rail@eline{
   398 \rail@tmpb=\rail@x
   399 \advance\rail@tmpb by -\rail@ex
   400 \rail@put{\line(-1,0){\number\rail@tmpb}}
   401 }
   402 
   403 \def\rail@sety#1{
   404 \rail@y=#1
   405 \multiply\rail@y by -\rail@boxsp
   406 \advance\rail@y by -\rail@boxht
   407 }
   408 
   409 % \rail@begin{HEIGHT}{NAME} : begin a railroad diagram of height HEIGHT
   410 %
   411 % \rail@end : end a railroad diagram
   412 %
   413 % \rail@expand{IDENT} : expand IDENT
   414 
   415 \def\rail@begin#1#2{
   416 \item[]
   417 \begin{minipage}[t]{\linewidth}
   418 \ifx\@empty#2\else
   419 {\rail@namefont \rail@expand{#2}}\\*[\railnamesep]
   420 \fi
   421 \unitlength=\railunit
   422 \rail@tmpa=#1
   423 \multiply\rail@tmpa by \rail@boxsp
   424 \begin{picture}(0,\number\rail@tmpa)(0,-\number\rail@tmpa)
   425 \rail@ex=0
   426 \rail@rx=0
   427 \rail@x=\rail@extra
   428 \rail@sx=\rail@x
   429 \rail@sety{0}
   430 }
   431 
   432 \def\rail@end{
   433 \advance\rail@x by \rail@extra
   434 \rail@eline
   435 \end{picture}
   436 \end{minipage}
   437 }
   438 
   439 \def\rail@expand#1{\@ifundefined{rail@t@#1}{#1}{\csname rail@t@#1\endcsname}}
   440 
   441 % \rail@token{TEXT}[ANNOT] : format token TEXT with annotation
   442 %
   443 % \rail@ctoken{TEXT}[ANNOT] : format token TEXT centered with annotation
   444 %
   445 % \rail@nont{TEXT}[ANNOT] : format nonterminal TEXT with annotation
   446 %
   447 % \rail@cnont{TEXT}[ANNOT] : format nonterminal TEXT centered with annotation
   448 %
   449 % \rail@term{TEXT}[ANNOT] : format terminal TEXT with annotation
   450 %
   451 % \rail@cterm{TEXT}[ANNOT] : format terminal TEXT centered with annotation
   452 %
   453 % \rail@annote[TEXT] : format TEXT as annotation
   454 
   455 \def\rail@token#1[#2]{
   456 \rail@setbox{%
   457 {\rail@termfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   458 }
   459 \rail@oval
   460 }
   461 
   462 \def\rail@ctoken#1[#2]{
   463 \rail@setbox{%
   464 {\rail@termfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   465 }
   466 \rail@coval
   467 }
   468 
   469 \def\rail@nont#1[#2]{
   470 \rail@setbox{%
   471 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   472 }
   473 \rail@frame
   474 }
   475 
   476 \def\rail@cnont#1[#2]{
   477 \rail@setbox{%
   478 {\rail@nontfont \rail@expand{#1}}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   479 }
   480 \rail@cframe
   481 }
   482 
   483 \def\rail@term#1[#2]{
   484 \rail@setbox{%
   485 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   486 }
   487 \rail@oval
   488 }
   489 
   490 \def\rail@cterm#1[#2]{
   491 \rail@setbox{%
   492 {\rail@termfont #1}\ifx\@empty#2\else\ {\rail@annofont #2}\fi
   493 }
   494 \rail@coval
   495 }
   496 
   497 \def\rail@annote[#1]{
   498 \rail@setbox{\rail@annofont #1}
   499 \rail@text
   500 }
   501 
   502 % \rail@box : temporary box for \rail@oval and \rail@frame
   503 %
   504 % \rail@setbox{TEXT} : set \rail@box to TEXT, set \rail@tmpa to width
   505 %
   506 % \rail@oval : format \rail@box of width \rail@tmpa inside an oval
   507 %
   508 % \rail@coval : same as \rail@oval, but centered between \rail@x and
   509 %               \rail@mx
   510 %
   511 % \rail@frame : format \rail@box of width \rail@tmpa inside a frame
   512 %
   513 % \rail@cframe : same as \rail@frame, but centered between \rail@x and
   514 %                \rail@mx
   515 %
   516 % \rail@text : format \rail@box of width \rail@tmpa above the line
   517 
   518 \newbox\rail@box
   519 
   520 \def\rail@setbox#1{
   521 \setbox\rail@box\hbox{\strut#1}
   522 \rail@tmpa=\wd\rail@box
   523 \divide\rail@tmpa by \railunit
   524 }
   525 
   526 \def\rail@oval{
   527 \advance\rail@x by \rail@boxlf
   528 \rail@eline
   529 \advance\rail@tmpa by \rail@ovalsp
   530 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
   531 \rail@tmpb=\rail@tmpa
   532 \divide\rail@tmpb by 2
   533 \advance\rail@y by -\rail@boxhht
   534 \rail@put{\makebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
   535 \advance\rail@y by \rail@boxhht
   536 \advance\rail@x by \rail@tmpb
   537 \rail@put{\oval(\number\rail@tmpa,\number\rail@boxht)}
   538 \advance\rail@x by \rail@tmpb
   539 \rail@ex=\rail@x
   540 \advance\rail@x by \rail@boxrt
   541 }
   542 
   543 \def\rail@coval{
   544 \rail@tmpb=\rail@tmpa
   545 \advance\rail@tmpb by \rail@ovalsp
   546 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
   547 \advance\rail@tmpb by \rail@boxlf
   548 \advance\rail@tmpb by \rail@boxrt
   549 \rail@tmpc=\rail@mx
   550 \advance\rail@tmpc by -\rail@x
   551 \advance\rail@tmpc by -\rail@tmpb
   552 \divide\rail@tmpc by 2
   553 \ifnum\rail@tmpc>0
   554 \advance\rail@x by \rail@tmpc
   555 \fi
   556 \rail@oval
   557 }
   558 
   559 \def\rail@frame{
   560 \advance\rail@x by \rail@boxlf
   561 \rail@eline
   562 \advance\rail@tmpa by \rail@framesp
   563 \ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
   564 \advance\rail@y by -\rail@boxhht
   565 \rail@put{\framebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
   566 \advance\rail@y by \rail@boxhht
   567 \advance\rail@x by \rail@tmpa
   568 \rail@ex=\rail@x
   569 \advance\rail@x by \rail@boxrt
   570 }
   571 
   572 \def\rail@cframe{
   573 \rail@tmpb=\rail@tmpa
   574 \advance\rail@tmpb by \rail@framesp
   575 \ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
   576 \advance\rail@tmpb by \rail@boxlf
   577 \advance\rail@tmpb by \rail@boxrt
   578 \rail@tmpc=\rail@mx
   579 \advance\rail@tmpc by -\rail@x
   580 \advance\rail@tmpc by -\rail@tmpb
   581 \divide\rail@tmpc by 2
   582 \ifnum\rail@tmpc>0
   583 \advance\rail@x by \rail@tmpc
   584 \fi
   585 \rail@frame
   586 }
   587 
   588 \def\rail@text{
   589 \advance\rail@x by \rail@textlf
   590 \advance\rail@y by \rail@textup
   591 \rail@put{\box\rail@box}
   592 \advance\rail@y by -\rail@textup
   593 \advance\rail@x by \rail@tmpa
   594 \advance\rail@x by \rail@textrt
   595 }
   596 
   597 % alternatives
   598 %
   599 % \rail@jx \rail@jy : current join point
   600 %
   601 % \rail@gx \rail@gy \rail@gex \rail@grx : global versions of \rail@x etc,
   602 %                                         to pass values over group closings
   603 %
   604 % \rail@mx : maximum x so far
   605 %
   606 % \rail@sy : starting \rail@y for alternatives
   607 %
   608 % \rail@jput : put at (\rail@jx,\rail@jy)
   609 %
   610 % \rail@joval[PART] : put \oval[PART] with adjust
   611 
   612 \newcount\rail@jx
   613 \newcount\rail@jy
   614 
   615 \newcount\rail@gx
   616 \newcount\rail@gy
   617 \newcount\rail@gex
   618 \newcount\rail@grx
   619 
   620 \newcount\rail@sy
   621 \newcount\rail@mx
   622 
   623 \def\rail@jput{
   624 \put(\number\rail@jx,\number\rail@jy)
   625 }
   626 
   627 \def\rail@joval[#1]{
   628 \advance\rail@jx by \rail@joinadj
   629 \rail@jput{\oval(\number\rail@joinsz,\number\rail@joinsz)[#1]}
   630 \advance\rail@jx by -\rail@joinadj
   631 }
   632 
   633 % \rail@barsplit : incoming split for '|'
   634 %
   635 % \rail@plussplit : incoming split for '+'
   636 %
   637 
   638 \def\rail@barsplit{
   639 \advance\rail@jy by -\rail@joinhsz
   640 \rail@joval[tr]
   641 \advance\rail@jx by \rail@joinhsz
   642 }
   643 
   644 \def\rail@plussplit{
   645 \advance\rail@jy by -\rail@joinhsz
   646 \advance\rail@jx by \rail@joinsz
   647 \rail@joval[tl]
   648 \advance\rail@jx by -\rail@joinhsz
   649 }
   650 
   651 % \rail@alt{SPLIT} : start alternatives with incoming split SPLIT
   652 %
   653 
   654 \def\rail@alt#1{
   655 \rail@sy=\rail@y
   656 \rail@jx=\rail@x
   657 \rail@jy=\rail@y
   658 \advance\rail@x by \rail@joinsz
   659 \rail@mx=0
   660 \let\rail@list=\@empty
   661 \let\rail@comma=\@empty
   662 \let\rail@split=#1
   663 \begingroup
   664 \rail@sx=\rail@x
   665 \rail@rx=0
   666 }
   667 
   668 % \rail@nextalt{FIX}{Y} : start next alternative at vertical position Y
   669 %                         and fix-up FIX
   670 %
   671 
   672 \def\rail@nextalt#1#2{
   673 \global\rail@gx=\rail@x
   674 \global\rail@gy=\rail@y
   675 \global\rail@gex=\rail@ex
   676 \global\rail@grx=\rail@rx
   677 \endgroup
   678 #1
   679 \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
   680 \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
   681 \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
   682 \def\rail@comma{,}
   683 \rail@split
   684 \let\rail@split=\@empty
   685 \rail@sety{#2}
   686 \rail@tmpa=\rail@jy
   687 \advance\rail@tmpa by -\rail@y
   688 \advance\rail@tmpa by -\rail@joinhsz
   689 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   690 \rail@jy=\rail@y
   691 \advance\rail@jy by \rail@joinhsz
   692 \advance\rail@jx by \rail@joinhsz
   693 \rail@joval[bl]
   694 \advance\rail@jx by -\rail@joinhsz
   695 \rail@ex=\rail@x
   696 \begingroup
   697 \rail@sx=\rail@x
   698 \rail@rx=0
   699 }
   700 
   701 % \rail@barjoin : outgoing join for first '|' alternative
   702 %
   703 % \rail@plusjoin : outgoing join for first '+' alternative
   704 %
   705 % \rail@altjoin : join for subsequent alternative
   706 %
   707 
   708 \def\rail@barjoin{
   709 \ifnum\rail@y<\rail@sy
   710 \global\rail@gex=\rail@jx
   711 \else
   712 \global\rail@gex=\rail@ex
   713 \fi
   714 \advance\rail@jy by -\rail@joinhsz
   715 \rail@joval[tl]
   716 \advance\rail@jx by -\rail@joinhsz
   717 \ifnum\rail@y<\rail@sy
   718 \rail@altjoin
   719 \fi
   720 }
   721 
   722 \def\rail@plusjoin{
   723 \global\rail@gex=\rail@ex
   724 \advance\rail@jy by -\rail@joinhsz
   725 \advance\rail@jx by -\rail@joinsz
   726 \rail@joval[tr]
   727 \advance\rail@jx by \rail@joinhsz
   728 }
   729 
   730 \def\rail@altjoin{
   731 \rail@eline
   732 \rail@tmpa=\rail@jy
   733 \advance\rail@tmpa by -\rail@y
   734 \advance\rail@tmpa by -\rail@joinhsz
   735 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   736 \rail@jy=\rail@y
   737 \advance\rail@jy by \rail@joinhsz
   738 \advance\rail@jx by -\rail@joinhsz
   739 \rail@joval[br]
   740 \advance\rail@jx by \rail@joinhsz
   741 }
   742 
   743 % \rail@eltsplit EX:Y; : split EX:Y into \rail@ex \rail@y
   744 %
   745 % \rail@endalt{JOIN} : end alternatives with outgoing join JOIN
   746 
   747 \def\rail@eltsplit#1:#2;{\rail@ex=#1\rail@y=#2}
   748 
   749 \def\rail@endalt#1{
   750 \global\rail@gx=\rail@x
   751 \global\rail@gy=\rail@y
   752 \global\rail@gex=\rail@ex
   753 \global\rail@grx=\rail@rx
   754 \endgroup
   755 \ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
   756 \ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
   757 \edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
   758 \rail@x=\rail@mx
   759 \rail@jx=\rail@x
   760 \rail@jy=\rail@sy
   761 \advance\rail@jx by \rail@joinsz
   762 \let\rail@join=#1
   763 \@for\rail@elt:=\rail@list\do{
   764 \expandafter\rail@eltsplit\rail@elt;
   765 \rail@join
   766 \let\rail@join=\rail@altjoin
   767 }
   768 \rail@x=\rail@mx
   769 \rail@y=\rail@sy
   770 \rail@ex=\rail@gex
   771 \advance\rail@x by \rail@joinsz
   772 }
   773 
   774 % \rail@bar : start '|' alternatives
   775 %
   776 % \rail@nextbar : next '|' alternative
   777 %
   778 % \rail@endbar : end '|' alternatives
   779 %
   780 
   781 \def\rail@bar{
   782 \rail@alt\rail@barsplit
   783 }
   784 
   785 \def\rail@nextbar{
   786 \rail@nextalt\relax
   787 }
   788 
   789 \def\rail@endbar{
   790 \rail@endalt\rail@barjoin
   791 }
   792 
   793 % \rail@plus : start '+' alternatives
   794 %
   795 % \rail@nextplus: next '+' alternative
   796 %
   797 % \rail@endplus : end '+' alternatives
   798 %
   799 
   800 \def\rail@plus{
   801 \rail@alt\rail@plussplit
   802 }
   803 
   804 \def\rail@nextplus{
   805 \rail@nextalt\rail@fixplus
   806 }
   807 
   808 \def\rail@fixplus{
   809 \ifnum\rail@gy<\rail@sy
   810 \begingroup
   811 \rail@x=\rail@gx
   812 \rail@y=\rail@gy
   813 \rail@ex=\rail@gex
   814 \rail@rx=\rail@grx
   815 \ifnum\rail@x<\rail@rx
   816 \rail@x=\rail@rx
   817 \fi
   818 \rail@eline
   819 \rail@jx=\rail@x
   820 \rail@jy=\rail@y
   821 \advance\rail@jy by \rail@joinhsz
   822 \rail@joval[br]
   823 \advance\rail@jx by \rail@joinhsz
   824 \rail@tmpa=\rail@sy
   825 \advance\rail@tmpa by -\rail@joinhsz
   826 \advance\rail@tmpa by -\rail@jy
   827 \rail@jput{\line(0,1){\number\rail@tmpa}}
   828 \rail@jy=\rail@sy
   829 \advance\rail@jy by -\rail@joinhsz
   830 \advance\rail@jx by \rail@joinhsz
   831 \rail@joval[tl]
   832 \advance\rail@jy by \rail@joinhsz
   833 \global\rail@gx=\rail@jx
   834 \global\rail@gy=\rail@jy
   835 \global\rail@gex=\rail@gx
   836 \global\rail@grx=\rail@rx
   837 \endgroup
   838 \fi
   839 }
   840 
   841 \def\rail@endplus{
   842 \rail@endalt\rail@plusjoin
   843 }
   844 
   845 % \rail@cr{Y} : carriage return to vertical position Y
   846 
   847 \def\rail@cr#1{
   848 \rail@tmpa=\rail@sx
   849 \advance\rail@tmpa by \rail@joinsz
   850 \ifnum\rail@x<\rail@tmpa\rail@x=\rail@tmpa\fi
   851 \rail@eline
   852 \rail@jx=\rail@x
   853 \rail@jy=\rail@y
   854 \advance\rail@x by \rail@joinsz
   855 \ifnum\rail@x>\rail@rx\rail@rx=\rail@x\fi
   856 \advance\rail@jy by -\rail@joinhsz
   857 \rail@joval[tr]
   858 \advance\rail@jx by \rail@joinhsz
   859 \rail@sety{#1}
   860 \rail@tmpa=\rail@jy
   861 \advance\rail@tmpa by -\rail@y
   862 \advance\rail@tmpa by -\rail@boxsp
   863 \advance\rail@tmpa by -\rail@joinhsz
   864 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   865 \rail@jy=\rail@y
   866 \advance\rail@jy by \rail@boxsp
   867 \advance\rail@jy by \rail@joinhsz
   868 \advance\rail@jx by -\rail@joinhsz
   869 \rail@joval[br]
   870 \advance\rail@jy by -\rail@joinhsz
   871 \rail@tmpa=\rail@jx
   872 \advance\rail@tmpa by -\rail@sx
   873 \advance\rail@tmpa by -\rail@joinhsz
   874 \rail@jput{\line(-1,0){\number\rail@tmpa}}
   875 \rail@jx=\rail@sx
   876 \advance\rail@jx by \rail@joinhsz
   877 \advance\rail@jy by -\rail@joinhsz
   878 \rail@joval[tl]
   879 \advance\rail@jx by -\rail@joinhsz
   880 \rail@tmpa=\rail@boxsp
   881 \advance\rail@tmpa by -\rail@joinsz
   882 \rail@jput{\line(0,-1){\number\rail@tmpa}}
   883 \advance\rail@jy by -\rail@tmpa
   884 \advance\rail@jx by \rail@joinhsz
   885 \rail@joval[bl]
   886 \rail@x=\rail@jx
   887 \rail@ex=\rail@x
   888 }