% ProgMacros.tex --- Stolfi April 9, 1984 3:50:04 pm PST
% Macros for programs
\message{programs ...}
% Parameters to be defined by user:
\newdimen\progindent % indentation of outermost bracket
\newdimen\proglevelindent % extra indentation per level
\newdimen\progstepindent % indentation of step text (exc. step number)
% relative to innermost bracket
\newdimen\progcommindent % indent. of comment text rel. innermost bracket
\newdimen\progcontindent % extra indentation of continuation lines
\newdimen\progthickness % thickness of block brackets
\newglue\progvsep % extra skip between steps (no stretch)
%also \kw = keyword font (say, \def\kw{\tt})
% PROGRAM BODY
% Usage:
% \fundef\Foo{Foo}
%
% \progbody
% procedure $\Foo(x) =\null$
% \begblock
% while $x<0$ do
% \begblock
% $x — 0$
% \rem{At this point either $x\neq\pi$ or $x=\pi$}
% $x — x + 1$
% ...
% \endblock
% \endblock
% \endbody
%
\outer\def\progbody{\smallvbreak
\begingroup
\parindent\z@ \hangindent\z@ \hangafter\z@
\leftglue\z@\rightglue\z@
\parsep\z@ \baselinesep-\p@ \linesep\z@
\nb@rs\z@ \st@pwidth\hsize
\advance\st@pwidth by -\progindent
\mathcode`\:="603A % treat colon as punctuation

\def\begblock{\begingroup
\advance\nb@rs by 1 \proge@r\z@\z@
\advance\st@pwidth by -\proglevelindent\par\pr@glin@}

\def\endblock{\proge@r\z@\z@\endgroup\par\pr@glin@}

\def\endbody{\endgroup\par\medvbreak}

\def\rem##1{\pr@gitem\progcommindent{\normalsize\it
\hmode\strut ##1\strut}\par\pr@glin@}

\obeylines
\pr@glin@}
% \pr@glin@ eats things up to next <cr>, and
% calls \pr@gstep or \pr@gcomm if appropriate.
\def\pr@glin@{\futurelet\next\pr@glin@@}
% the following must be read with \endlinechar=-1:
{\catcode`\^^M=\active
\global\long\def\pr@glin@@#1^^M{
\ifx\next\par \def\next{\pr@glin@}
\else \ifx\next\rem \def\next{#1}
\else \ifx\next\begblock % do nothing
\else \ifx\next\endblock % do nothin
\else \ifx\next\endbody % do nothin
\else \def\next{\pr@gitem\progstepindent{\normalsize\kw
\hmode\strut #1\strut}\par\pr@glin@}\fi\fi\fi\fi\fi\next}}
% COMMON KEYWORDS
\message{program keywords ...}
% Define new keywords, procedure names, and program identifiers
\def\ky#1{\hbox{\kw #1}} % horiz text in keyword font
\def\fn#1{\mathop{\tt #1}} % functions
\def\vr#1{{\tt #1}} % variables
\def\keydef#1#2{\def#1{\hbox{\kw #2}}}
\def\fundef#1#2{\def#1{\mathop{\tt #2}}}
\def\vardef#1#2{\def#1{{\tt #2}}}
% INTERNAL MACROS
% No user-serviceable parts below.
% Internal program step.
\long\def\pr@gitem#1#2{
\hbox
{\progvb@rs\hskip -\proglevelindent
\hskip #1
\vbox{\hsize=\st@pwidth \advance\hsize by -#1
\vskip 0.5\progvsep
\vbox{\hangindent\progcontindent\hangafter1 #2}
\vskip 0.5\progvsep}
\hfil}}
% "ear" for block brackets
\def\proge@r#1#2{\par\penalty\@M
\hbox
{\progvb@rs\hskip -\proglevelindent
\vbox{\vskip #1
\hrule height \progthickness width 0.4em
\vskip #2}
\hfil}
\penalty\@M}
% generates pieces of left brackets
\def\progvb@rs{\hskip \progindent
\rep\nb@rs{\vrule width\progthickness
\hskip-\progthickness \hskip\proglevelindent}}