%\filename{progmacros.tex}
%\edited{last by stolfi on Sat Mar  7 02:34:37 1987}

\catcode`@=11 \endlinechar=-1

% Macros for programs

  \message{programs ...}

  % Usage:

  % \fundef\NewFoo{New\_Foo}
  % \vardef\xsum{x\_sum}
  % 
  % \progbody
  %   procedure $\NewFoo(x) =\null$
  %     \begblock
  %       while $x<0$ do
  %         \begblock
  %           $x \gets 0$
  %           \rem{At this point either $x\neq\pi$ or $x=\pi$}
  %           $x \gets x + 1$
  %           $\xsum\gets \xsum+x$
  %           ...
  %         \endblock
  %       return $\xsum$
  %     \endblock
  % \endbody


% DIMENSIONAL PARAMETERS

  % Parameters that can be redefined 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)

    % Standard settings:

    \progindent=20pt % indentation of outermost bracket
    \progthickness = 0.6pt  % thickness of block brackets
    \proglevelindent = 12pt % extra indent. per level (incl. \progthickness)
    \progstepindent = 4pt   % indent. of prog. text rel. to innermost bracket
    \progcommindent = 12pt  % indent. of \rem text rel. to innermost bracket
    \progcontindent = 8pt   % extra indentation of continuation lines
    \progvsep = 2pt % extra separation between steps

    % Comment brackets
    
    \def\progopenrem{\hbox to\progcontindent{$[\![$\hss}}
    \def\progcloserem{\hbox to \progcontindent{\hss$]\!]$}}

    % Fonts (can be redefined):
  
    \def\progremfont{\it} % Font for comments
    \def\progkeyfont{\bf} % Font for program keywords (and types)
    \def\progfunfont{\it} % Font for function and procedure names
    \def\progvarfont{\it} % Font for variables

% COMMON KEYWORDS

  \message{program keywords ...}

  % Define new keywords, procedure names, and program identifiers

    \def\keydef#1#2{\def#1{\hbox{\progkeyfont #2}}}
    \def\fundef#1#2{\def#1{\mathop{\progfunfont #2}}}
    \def\vardef#1#2{\def#1{{\progvarfont #2}}}

% PROGRAM BODY

  % Special symbol definitions for program text:
    
    \def\_{{\hskip0.1em}} % Thin space inside identifiers

    % Special definitions for \prg and \progbody:
    %   treat colon as punctuation, for :=
    %   define \: to be colon+space (for declarations)
    \def\pr@gstyledefs{\mathcode`\:="603A\def\:{:\;}}

  % Program fragments in horiz. text:

    \def\prg#1{\hbox{\pr@gstyledefs\progkeyfont #1}}
    
  % Program displays:
    
    \outer\def\progbody{\medvbreak
      \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
        \pr@gstyledefs

        \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{\hmode
            \progremfont\progopenrem\strut ##1\strut\progcloserem
          }\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\progkeyfont
           \hmode\strut #1\strut}\par\pr@glin@}\fi\fi\fi\fi\fi\next}}

% 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}}

\catcode`@=12 \endlinechar=`\^^M

% END
