doc-src/rail.sty
author wenzelm
Thu, 20 Feb 1997 15:15:17 +0100
changeset 2658 13ba951a4572
child 3097 ae362c99a635
permissions -rw-r--r--
added this file;

% rail.sty - style file to support railroad diagrams
%
% 09-Jul-90 L. Rooijakkers
% 08-Oct-90 L. Rooijakkers	fixed centering bug when \rail@tmpc<0.
% 07-Feb-91 L. Rooijakkers	added \railoptions command, indexing
% 08-Feb-91 L. Rooijakkers	minor fixes
%
% This style file needs to be used in conjunction with the 'rail'
% program. Running LaTeX as 'latex file' produces file.rai, which should be
% processed by Rail with 'rail file'. This produces file.rao, which will
% be picked up by LaTeX on the next 'latex file' run.
%
% LaTeX will warn if there is no file.rao or it's out of date.
%
% The macros in this file thus consist of two parts: those that read and
% write the .rai and .rao files, and those that do the actual formatting
% of the railroad diagrams.

% railroad read/write macros
%
% \begin{rail} TEXT \end{rail} : TEXT is written out to the .rai file,
%                                as \rail@i{NR}{TEXT}. Then the matching
%                                \rail@o{NR}{FMT} from the .rao file is
%                                executed (if defined).
%
% \railoptions{OPTIONS} : OPTIONS are written out to the .rai file,
%                         as \rail@p{OPTIONS}.
%
% \railterm{IDENT,IDENT,...} : format IDENT as terminals. writes out
%                              \rail@t{IDENT} to the .rai file and
%                              defines \rail@t@IDENT as \rail@termfont IDENT.
%
% \railtoken{IDENT}{TEXT} : format IDENT as terminal TEXT. writes out
%                           \rail@t{IDENT} to the .rai file and defines
%                           \rail@t@IDENT as TEXT.
%
% \rail@nr : railroad diagram counter, starts at 1
%
% \ifrail@match : current \rail@i{NR}{TEXT} matches
%
% \rail@first :	actions to be done first. read in .rao file,
%               open .rai file if \@filesw true, undefine \rail@first.
%               executed from \begin{rail} and \railtoken.
%
% \rail@i{NR}{TEXT} : defines \rail@i@NR as TEXT. written to the .rai
%                     file by \rail, read from the .rao file by
%                     \rail@first
%
% \rail@t{IDENT} : tells Rail that IDENT is to be custom formatted,
%                  written to the .rai file by \railterm and \railtoken.
%
% \rail@o{NR}{TEXT} : defines \rail@o@NR as TEXT, read from the .rao
%                     file by \rail@first.
%
% \rail@p{OPTIONS} : pass options to rail, written to the .rai file by
%                    \railoptions
%
% \rail@warn : warn user for mismatching diagrams
%
% \rail@endwarn : either \relax or \rail@warn
%
% \rail@enddocument : original \enddocument
%
% \enddocument : checks \ifrail@all

\newcount\rail@nr
\rail@nr=1

\newif\ifrail@all
\rail@alltrue

\newif\ifrail@match

\def\rail@first{
\makeatletter
\@input{\jobname.rao}
\makeatother
\if@filesw
\newwrite\tf@rai
\immediate\openout\tf@rai\jobname.rai\relax
\fi
\global\let\rail@first=\relax
}

\long\def\rail#1\end#2{
\end{#2}
\rail@first
\begingroup
\let\\=\relax
\global\edef\rail@i@{#1}
\endgroup
\@ifundefined{tf@rai}{}{
\begingroup
\let\\=\relax
\immediate\write\tf@rai{\noexpand\rail@i{\number\rail@nr}{\rail@i@}}
\endgroup
}
\rail@matchtrue
\@ifundefined{rail@o@\number\rail@nr}{\rail@matchfalse}{}
\expandafter\ifx\csname rail@i@\number\rail@nr\endcsname\rail@i@
\else
\rail@matchfalse
\fi
\ifrail@match
\expandafter\relax\csname rail@o@\number\rail@nr\endcsname
\else
\@warning{Railroad diagram {\number\rail@nr} doesn't match}
\global\let\rail@endwarn=\rail@warn
\rail@begin{1}{}
\rail@setbox{\bf ???}
\rail@oval
\rail@end
\fi
\global\advance\rail@nr by 1
}

\def\railoptions#1{
\rail@first
\@writefile{rai}{\noexpand\rail@p{#1}}
}

\def\railterm#1{
\rail@first
\@for\rail@i@:=#1\do{
\@writefile{rai}{\noexpand\rail@t{\rail@i@}}
}
}

\def\railtoken#1#2{
\rail@first
\@writefile{rai}{\noexpand\rail@t{#1}}
\expandafter\def\csname rail@t@#1\endcsname{#2}
}

\long\def\rail@i#1#2{
\expandafter\gdef\csname rail@i@#1\endcsname{#2}
}

\def\rail@o#1#2{
\expandafter\gdef\csname rail@o@#1\endcsname{#2}
}

\def\rail@t#1{}

\def\rail@p#1{}

\def\rail@warn{
\@warning{Railroad diagram(s) may have changed. Use 'rail' and rerun}
}

\let\rail@endwarn=\relax

\let\rail@enddocument=\enddocument

\def\enddocument{
\rail@endwarn
\rail@enddocument
}

% index entry macro
%
% \rail@index{IDENT} : add index entry for IDENT

\def\rail@index#1{
\index{\rail@indexfont#1}
}

% railroad diagram formatting parameters (user level)
% all of these are copied into their internal versions by \railinit
%
% \railunit : \unitlength within railroad diagrams
% \railextra : extra length at outside of diagram
% \railboxheight : height of ovals and frames
% \railboxskip : vertical space between lines
% \railboxleft : space to the left of a box
% \railboxright : space to the right of a box
% \railovalspace : extra space around contents of oval
% \railframespace : extra space around contents of frame
% \railtextleft : space to the left of text
% \railtextright : space to the right of text
% \railtextup : space to lift text up
% \railjoinsize : circle size of join/split arcs
% \railjoinadjust : space to adjust join
%
% \railnamesep : separator between name and rule body

\newdimen\railunit
\newdimen\railextra
\newdimen\railboxheight
\newdimen\railboxskip
\newdimen\railboxleft
\newdimen\railboxright
\newdimen\railovalspace
\newdimen\railframespace
\newdimen\railtextleft
\newdimen\railtextright
\newdimen\railtextup
\newdimen\railjoinsize
\newdimen\railjoinadjust
\newdimen\railnamesep

% internal versions of the formatting parameters
%
% \rail@extra   : \railextra
% \rail@boxht   : \railboxheight
% \rail@boxsp   : \railboxskip
% \rail@boxlf   : \railboxleft
% \rail@boxrt   : \railboxright
% \rail@boxhht  : \railboxheight / 2
% \rail@ovalsp  : \railovalspace
% \rail@framesp : \railframespace
% \rail@textlf	: \railtextleft
% \rail@textrt	: \railtextright
% \rail@textup	: \railtextup
% \rail@joinsz  : \railjoinsize
% \rail@joinhsz : \railjoinsize / 2
% \rail@joinadj : \railjoinadjust
%
% \railinit : internalize all of the parameters.

\newcount\rail@extra
\newcount\rail@boxht
\newcount\rail@boxsp
\newcount\rail@boxlf
\newcount\rail@boxrt
\newcount\rail@boxhht
\newcount\rail@ovalsp
\newcount\rail@framesp
\newcount\rail@textlf
\newcount\rail@textrt
\newcount\rail@textup
\newcount\rail@joinsz
\newcount\rail@joinhsz
\newcount\rail@joinadj

\def\railinit{
\rail@extra=\railextra
\divide\rail@extra by \railunit
\rail@boxht=\railboxheight
\divide\rail@boxht by \railunit
\rail@boxsp=\railboxskip
\divide\rail@boxsp by \railunit
\rail@boxlf=\railboxleft
\divide\rail@boxlf by \railunit
\rail@boxrt=\railboxright
\divide\rail@boxrt by \railunit
\rail@boxhht=\railboxheight
\divide\rail@boxhht by \railunit
\divide\rail@boxhht by 2
\rail@ovalsp=\railovalspace
\divide\rail@ovalsp by \railunit
\rail@framesp=\railframespace
\divide\rail@framesp by \railunit
\rail@textlf=\railtextleft
\divide\rail@textlf by \railunit
\rail@textrt=\railtextright
\divide\rail@textrt by \railunit
\rail@textup=\railtextup
\divide\rail@textup by \railunit
\rail@joinsz=\railjoinsize
\divide\rail@joinsz by \railunit
\rail@joinhsz=\railjoinsize
\divide\rail@joinhsz by \railunit
\divide\rail@joinhsz by 2
\rail@joinadj=\railjoinadjust
\divide\rail@joinadj by \railunit
}

% initialize the parameters

\railunit=1sp
\railextra=4ex
\railboxleft=1ex
\railboxright=1ex
\railovalspace=2ex
\railframespace=2ex
\railtextleft=1ex
\railtextright=1ex
\railjoinadjust=0pt
\railnamesep=1ex

\ifcase\@ptsize
% 10 pt
\railboxheight=16pt
\railboxskip=24pt
\railtextup=5pt
\railjoinsize=16pt
\or
% 11 pt
\railboxheight=16pt
\railboxskip=24pt
\railtextup=5pt
\railjoinsize=16pt
\or
% 12 pt
\railboxheight=20pt
\railboxskip=28pt
\railtextup=6pt
\railjoinsize=20pt
\fi

\railinit

% railroad formatting primitives
%
% \rail@x : current x
% \rail@y : current y
% \rail@ex : current end x
% \rail@sx : starting x for \rail@cr
% \rail@rx : rightmost previous x for \rail@cr
%
% \rail@tmpa : temporary count
% \rail@tmpb : temporary count
% \rail@tmpc : temporary count
%
% \rail@put : put at (\rail@x,\rail@y)
%
% \rail@eline : end line by drawing from \rail@ex to \rail@x
%
% \rail@sety{LEVEL} : set \rail@y to level LEVEL

\newcount\rail@x
\newcount\rail@y
\newcount\rail@ex
\newcount\rail@sx
\newcount\rail@rx

\newcount\rail@tmpa
\newcount\rail@tmpb
\newcount\rail@tmpc

\def\rail@put{\put(\number\rail@x,\number\rail@y)}

\def\rail@eline{
\rail@tmpb=\rail@x
\advance\rail@tmpb by -\rail@ex
\rail@put{\line(-1,0){\number\rail@tmpb}}
}

\def\rail@sety#1{
\rail@y=#1
\multiply\rail@y by -\rail@boxsp
\advance\rail@y by -\rail@boxht
}

% \rail@list : declarations for list environment
%
% \railparam{TEXT} : sets \rail@list to TEXT
%
% \rail@begin{HEIGHT}{NAME} : begin a railroad diagram of height HEIGHT
%
% \rail@end : end a railroad diagram

\def\rail@list{}

\def\railparam#1{
\def\rail@list{#1}
}

\newbox\tempbox

\def\rail@begin#1#2{
\medskip
\begin{list}{}{\rail@list}
\item[]
\vbox\bgroup
\ifx\@empty#2\else
{\rail@namefont #2}
\\*[\railnamesep]\nopagebreak
\fi
\unitlength=\railunit
\rail@tmpa=#1
\multiply\rail@tmpa by \rail@boxsp
\begin{picture}(0,\number\rail@tmpa)(0,-\number\rail@tmpa)
\rail@ex=0
\rail@rx=0
\rail@x=\rail@extra
\rail@sx=\rail@x
\rail@sety{0}
}

\def\rail@end{
\advance\rail@x by \rail@extra
\rail@eline
\end{picture}
\egroup
\end{list}
}

% \rail@tokenfont : format setup for \railtoken identifiers
%
% \rail@termfont : format setup for terminals
%
% \rail@nontfont : format setup for nonterminals
%
% \rail@annofont : format setup for annotations
%
% \rail@rulefont : format setup for rule names
%
% \rail@indexfont : format setup for index entry
%
% \railtokenfont{TEXT} : set \railtoken format setup to TEXT
%
% \railtermfont{TEXT} : set terminal format setup to TEXT
%
% \railnontermfont{TEXT} : set nonterminal format setup to TEXT
%
% \railannotatefont{TEXT} : set annotation format setup to TEXT
%
% \railnamefont{TEXT} : set rule name format setup to TEXT
%
% \railindexfont{TEXT} : set index entry format setup to TEXT

\let\rail@tokenfont=\tt
\let\rail@termfont=\tt
\let\rail@nontfont=\rm
\let\rail@annofont=\it
\let\rail@namefont=\it
\let\rail@indexfont=\it

\def\railtokenfont#1{
\def\rail@tokenfont{#1}
}

\def\railtermfont#1{
\def\rail@termfont{#1}
}

\def\railnontermfont#1{
\def\rail@nontfont{#1}
}

\def\railannotatefont#1{
\def\rail@annofont{#1}
}

\def\railnamefont#1{
\def\rail@namefont{#1}
}

\def\railindexfont#1{
\def\rail@indexfont{#1}
}

% \rail@token{TEXT} : format token TEXT
%
% \rail@ctoken{TEXT} : format token TEXT centered
%
% \rail@nont{TEXT} : format nonterminal TEXT
%
% \rail@cnont{TEXT} : format nonterminal TEXT centered
%
% \rail@cterm{TEXT} : format terminal TEXT
%
% \rail@cterm{TEXT} : format terminal TEXT centered
%
% \rail@annote[TEXT] : format TEXT as annotation
%
% \rail@annotebox[TEXT] : annotate box with TEXT

\def\rail@token#1{
\expandafter\@ifundefined{rail@t@#1}{
\rail@setbox{\rail@termfont #1}
}{
\rail@setbox{\rail@tokenfont \csname rail@t@#1\endcsname}
}
\rail@oval
}

\def\rail@ctoken#1{
\rail@setbox{\rail@tokenfont \csname rail@t@#1\endcsname}
\rail@coval
}

\def\rail@nont#1{
\rail@setbox{\rail@nontfont #1}
\rail@frame
}

\def\rail@cnont#1{
\rail@setbox{\rail@nontfont #1}
\rail@cframe
}

\def\rail@term#1{
\rail@setbox{\rail@termfont #1}
\rail@oval
}

\def\rail@cterm#1{
\rail@setbox{\rail@termfont #1}
\rail@coval
}

\def\rail@annote[#1]{
\rail@setbox{\rail@annofont #1}
\rail@text
}

\def\rail@annotebox[#1]{
\ \rail@annofont #1
}

% \rail@box : temporary box for \rail@oval and \rail@frame
%
% \rail@setbox{TEXT} : set \rail@box to TEXT, set \rail@tmpa to width
%
% \rail@oval : format \rail@box of width \rail@tmpa inside an oval
%
% \rail@coval : same as \rail@oval, but centered between \rail@x and
%               \rail@mx
%
% \rail@frame : format \rail@box of width \rail@tmpa inside a frame
%
% \rail@cframe : same as \rail@frame, but centered between \rail@x and
%                \rail@mx
%
% \rail@text : format \rail@box of width \rail@tmpa above the line

\newbox\rail@box

\def\rail@setbox#1{
\setbox\rail@box\hbox{\strut#1}
\rail@tmpa=\wd\rail@box
\divide\rail@tmpa by \railunit
}

\def\rail@oval{
\advance\rail@x by \rail@boxlf
\rail@eline
\advance\rail@tmpa by \rail@ovalsp
\ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
\rail@tmpb=\rail@tmpa
\divide\rail@tmpb by 2
\advance\rail@y by -\rail@boxhht
\rail@put{\makebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
\advance\rail@y by \rail@boxhht
\advance\rail@x by \rail@tmpb
\rail@put{\oval(\number\rail@tmpa,\number\rail@boxht)}
\advance\rail@x by \rail@tmpb
\rail@ex=\rail@x
\advance\rail@x by \rail@boxrt
}

\def\rail@coval{
\rail@tmpb=\rail@tmpa
\advance\rail@tmpb by \rail@ovalsp
\ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
\advance\rail@tmpb by \rail@boxlf
\advance\rail@tmpb by \rail@boxrt
\rail@tmpc=\rail@mx
\advance\rail@tmpc by -\rail@x
\advance\rail@tmpc by -\rail@tmpb
\divide\rail@tmpc by 2
\ifnum\rail@tmpc>0
\advance\rail@x by \rail@tmpc
\fi
\rail@oval
}

\def\rail@frame{
\advance\rail@x by \rail@boxlf
\rail@eline
\advance\rail@tmpa by \rail@framesp
\ifnum\rail@tmpa<\rail@boxht\rail@tmpa=\rail@boxht\fi
\advance\rail@y by -\rail@boxhht
\rail@put{\framebox(\number\rail@tmpa,\number\rail@boxht){\box\rail@box}}
\advance\rail@y by \rail@boxhht
\advance\rail@x by \rail@tmpa
\rail@ex=\rail@x
\advance\rail@x by \rail@boxrt
}

\def\rail@cframe{
\rail@tmpb=\rail@tmpa
\advance\rail@tmpb by \rail@framesp
\ifnum\rail@tmpb<\rail@boxht\rail@tmpb=\rail@boxht\fi
\advance\rail@tmpb by \rail@boxlf
\advance\rail@tmpb by \rail@boxrt
\rail@tmpc=\rail@mx
\advance\rail@tmpc by -\rail@x
\advance\rail@tmpc by -\rail@tmpb
\divide\rail@tmpc by 2
\ifnum\rail@tmpc>0
\advance\rail@x by \rail@tmpc
\fi
\rail@frame
}

\def\rail@text{
\advance\rail@x by \rail@textlf
\advance\rail@y by \rail@textup
\rail@put{\box\rail@box}
\advance\rail@y by -\rail@textup
\advance\rail@x by \rail@tmpa
\advance\rail@x by \rail@textrt
}

% alternatives
%
% \rail@jx \rail@jy : current join point
%
% \rail@gx \rail@gy \rail@gex \rail@grx : global versions of \rail@x etc,
%                                         to pass values over group closings
%
% \rail@mx : maximum x so far
%
% \rail@sy : starting \rail@y for alternatives
%
% \rail@jput : put at (\rail@jx,\rail@jy)
%
% \rail@joval[PART] : put \oval[PART] with adjust

\newcount\rail@jx
\newcount\rail@jy

\newcount\rail@gx
\newcount\rail@gy
\newcount\rail@gex
\newcount\rail@grx

\newcount\rail@sy
\newcount\rail@mx

\def\rail@jput{
\put(\number\rail@jx,\number\rail@jy)
}

\def\rail@joval[#1]{
\advance\rail@jx by \rail@joinadj
\rail@jput{\oval(\number\rail@joinsz,\number\rail@joinsz)[#1]}
\advance\rail@jx by -\rail@joinadj
}

% \rail@barsplit : incoming split for '|'
%
% \rail@plussplit : incoming split for '+'
%

\def\rail@barsplit{
\advance\rail@jy by -\rail@joinhsz
\rail@joval[tr]
\advance\rail@jx by \rail@joinhsz
}

\def\rail@plussplit{
\advance\rail@jy by -\rail@joinhsz
\advance\rail@jx by \rail@joinsz
\rail@joval[tl]
\advance\rail@jx by -\rail@joinhsz
}

% \rail@alt{SPLIT} : start alternatives with incoming split SPLIT
%

\def\rail@alt#1{
\rail@sy=\rail@y
\rail@jx=\rail@x
\rail@jy=\rail@y
\advance\rail@x by \rail@joinsz
\rail@mx=0
\let\rail@list=\@empty
\let\rail@comma=\@empty
\let\rail@split=#1
\begingroup
\rail@sx=\rail@x
\rail@rx=0
}

% \rail@nextalt{FIX}{Y} : start next alternative at vertical position Y
%                         and fix-up FIX
%

\def\rail@nextalt#1#2{
\global\rail@gx=\rail@x
\global\rail@gy=\rail@y
\global\rail@gex=\rail@ex
\global\rail@grx=\rail@rx
\endgroup
#1
\ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
\ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
\edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
\def\rail@comma{,}
\rail@split
\let\rail@split=\@empty
\rail@sety{#2}
\rail@tmpa=\rail@jy
\advance\rail@tmpa by -\rail@y
\advance\rail@tmpa by -\rail@joinhsz
\rail@jput{\line(0,-1){\number\rail@tmpa}}
\rail@jy=\rail@y
\advance\rail@jy by \rail@joinhsz
\advance\rail@jx by \rail@joinhsz
\rail@joval[bl]
\advance\rail@jx by -\rail@joinhsz
\rail@ex=\rail@x
\begingroup
\rail@sx=\rail@x
\rail@rx=0
}

% \rail@barjoin : outgoing join for first '|' alternative
%
% \rail@plusjoin : outgoing join for first '+' alternative
%
% \rail@altjoin : join for subsequent alternative
%

\def\rail@barjoin{
\ifnum\rail@y<\rail@sy
\global\rail@gex=\rail@jx
\else
\global\rail@gex=\rail@ex
\fi
\advance\rail@jy by -\rail@joinhsz
\rail@joval[tl]
\advance\rail@jx by -\rail@joinhsz
\ifnum\rail@y<\rail@sy
\rail@altjoin
\fi
}

\def\rail@plusjoin{
\global\rail@gex=\rail@ex
\advance\rail@jy by -\rail@joinhsz
\advance\rail@jx by -\rail@joinsz
\rail@joval[tr]
\advance\rail@jx by \rail@joinhsz
}

\def\rail@altjoin{
\rail@eline
\rail@tmpa=\rail@jy
\advance\rail@tmpa by -\rail@y
\advance\rail@tmpa by -\rail@joinhsz
\rail@jput{\line(0,-1){\number\rail@tmpa}}
\rail@jy=\rail@y
\advance\rail@jy by \rail@joinhsz
\advance\rail@jx by -\rail@joinhsz
\rail@joval[br]
\advance\rail@jx by \rail@joinhsz
}

% \rail@eltsplit EX:Y; : split EX:Y into \rail@ex \rail@y
%
% \rail@endalt{JOIN} : end alternatives with outgoing join JOIN

\def\rail@eltsplit#1:#2;{\rail@ex=#1\rail@y=#2}

\def\rail@endalt#1{
\global\rail@gx=\rail@x
\global\rail@gy=\rail@y
\global\rail@gex=\rail@ex
\global\rail@grx=\rail@rx
\endgroup
\ifnum\rail@gx>\rail@mx\rail@mx=\rail@gx\fi
\ifnum\rail@grx>\rail@mx\rail@mx=\rail@grx\fi
\edef\rail@list{\rail@list\rail@comma\number\rail@gex:\number\rail@gy}
\rail@x=\rail@mx
\rail@jx=\rail@x
\rail@jy=\rail@sy
\advance\rail@jx by \rail@joinsz
\let\rail@join=#1
\@for\rail@elt:=\rail@list\do{
\expandafter\rail@eltsplit\rail@elt;
\rail@join
\let\rail@join=\rail@altjoin
}
\rail@x=\rail@mx
\rail@y=\rail@sy
\rail@ex=\rail@gex
\advance\rail@x by \rail@joinsz
}

% \rail@bar : start '|' alternatives
%
% \rail@nextbar : next '|' alternative
%
% \rail@endbar : end '|' alternatives
%

\def\rail@bar{
\rail@alt\rail@barsplit
}

\def\rail@nextbar{
\rail@nextalt\relax
}

\def\rail@endbar{
\rail@endalt\rail@barjoin
}

% \rail@plus : start '+' alternatives
%
% \rail@nextplus: next '+' alternative
%
% \rail@endplus : end '+' alternatives
%

\def\rail@plus{
\rail@alt\rail@plussplit
}

\def\rail@nextplus{
\rail@nextalt\rail@fixplus
}

\def\rail@fixplus{
\ifnum\rail@gy<\rail@sy
\begingroup
\rail@x=\rail@gx
\rail@y=\rail@gy
\rail@ex=\rail@gex
\rail@rx=\rail@grx
\ifnum\rail@x<\rail@rx
\rail@x=\rail@rx
\fi
\rail@eline
\rail@jx=\rail@x
\rail@jy=\rail@y
\advance\rail@jy by \rail@joinhsz
\rail@joval[br]
\advance\rail@jx by \rail@joinhsz
\rail@tmpa=\rail@sy
\advance\rail@tmpa by -\rail@joinhsz
\advance\rail@tmpa by -\rail@jy
\rail@jput{\line(0,1){\number\rail@tmpa}}
\rail@jy=\rail@sy
\advance\rail@jy by -\rail@joinhsz
\advance\rail@jx by \rail@joinhsz
\rail@joval[tl]
\advance\rail@jy by \rail@joinhsz
\global\rail@gx=\rail@jx
\global\rail@gy=\rail@jy
\global\rail@gex=\rail@gx
\global\rail@grx=\rail@rx
\endgroup
\fi
}

\def\rail@endplus{
\rail@endalt\rail@plusjoin
}

% \rail@cr{Y} : carriage return to vertical position Y

\def\rail@cr#1{
\rail@tmpa=\rail@sx
\advance\rail@tmpa by \rail@joinsz
\ifnum\rail@x<\rail@tmpa\rail@x=\rail@tmpa\fi
\rail@eline
\rail@jx=\rail@x
\rail@jy=\rail@y
\advance\rail@x by \rail@joinsz
\ifnum\rail@x>\rail@rx\rail@rx=\rail@x\fi
\advance\rail@jy by -\rail@joinhsz
\rail@joval[tr]
\advance\rail@jx by \rail@joinhsz
\rail@sety{#1}
\rail@tmpa=\rail@jy
\advance\rail@tmpa by -\rail@y
\advance\rail@tmpa by -\rail@boxsp
\advance\rail@tmpa by -\rail@joinhsz
\rail@jput{\line(0,-1){\number\rail@tmpa}}
\rail@jy=\rail@y
\advance\rail@jy by \rail@boxsp
\advance\rail@jy by \rail@joinhsz
\advance\rail@jx by -\rail@joinhsz
\rail@joval[br]
\advance\rail@jy by -\rail@joinhsz
\rail@tmpa=\rail@jx
\advance\rail@tmpa by -\rail@sx
\advance\rail@tmpa by -\rail@joinhsz
\rail@jput{\line(-1,0){\number\rail@tmpa}}
\rail@jx=\rail@sx
\advance\rail@jx by \rail@joinhsz
\advance\rail@jy by -\rail@joinhsz
\rail@joval[tl]
\advance\rail@jx by -\rail@joinhsz
\rail@tmpa=\rail@boxsp
\advance\rail@tmpa by -\rail@joinsz
\rail@jput{\line(0,-1){\number\rail@tmpa}}
\advance\rail@jy by -\rail@tmpa
\advance\rail@jx by \rail@joinhsz
\rail@joval[bl]
\rail@x=\rail@jx
\rail@ex=\rail@x
}