\documentclass[a4paper,10pt]{article}
\usepackage{noweb}

\input MANUAL.pagesize
\input MANUAL.mac
%\def\<{\hbox{\tt <}}
%\def\>{\hbox{\tt >}}
%\def\CC{C\raise.08ex\hbox{\tt ++\ }}
%\def\nat{\hbox{\rm\vrule\kern-0.045em N}}
%\def\real{\hbox{\rm\vrule\kern-0.035em R}}
%\def\tildeop{\hbox{$\sim$}}
%\def\circumflexop{\hbox{\^{}}}
%\newcommand\DP{\hspace{.1em}{::}\hspace{-.2em}} % symbol for ::

%\def\precond {{\it Precondition}: }
%\def\Labs#1{\hbox{$|\,#1\,|$}}

%\def\Litem#1{\hbox{{\tt <}#1{\tt >}\ }}%
%\def\Litem#1{\hbox{{\tt <}$#1${\tt >}\ }}
%\def\Litem#1{\hbox{{\tt <}$\mathit{#1}${\tt >}\ }}
%\def\Lvert{|}
%\def\sign{\mathop{\rm sign}}

%\def\3{\ss{}}

%\def\boxit#1{\vbox{\hrule\hbox{\vrule\kern3pt\vbox{#1}\kern3pt\vrule}\hrule}}

%def\co{\hbox{\tt //\ }}
%\def\'{\hbox{\tt "}}
%\def\CCC{C\raise.08ex\hbox{\tt ++}}
%\def\g++{g\hbox{\tt ++\ }} 

%\def\'{^\prime}
%\def\+{$+$}

%\def\refsign{\hbox{\tt \&}}


\setcounter{secnumdepth}{5}
\setcounter{tocdepth}{5}
\newcommand{\tc}[1]{$\backslash\mathit{#1}$}

\begin{document}

@

\title{The LEDA Tools for Manual Production and Documentation}
\author{Evelyn Haak \and Kurt Mehlhorn \and Stefan N\"{a}her \and Christian Uhrig}
\maketitle
\newpage

\tableofcontents
\newpage

\section{The Manual Page of the Documentation Tools}

% \input{doctools.spec} hier enkopieren.


LEDA offers tools for manual production and documentation.

\begin{verbatim}
       __________  weave ______   LaTeX source
      |
      |   ------- Lman --------   LaTeX source for manual page
    foo
      |   ------- Ldoc --------   LaTeX source for full documentation
      |
      |   ------- Fman --------   ASCII version of manual page
      |
      |__________ tangle ______   program

    
    foo's ------- Mkman -------   LaTeX source of manual

    foo's ------- Mkdvi -------   dvi versions of all manual pages
                                  in directory MANUAL/DVI

\end{verbatim}

Lman produces manual pages from header files suitably
augmented by so-called manual comments. Many examples can be found in the LEDA include directory (LEDAROOT/incl/LEDA). A manual comment starts with \verb-\*{\M- 
and ends with \verb-}*/-. Try \verb-Lman list- to see Lman in action.
If it does not work the error is very likely to be one of the following (if not, you should refer to the LEDA installation guide):

\begin{itemize}
\item The environment variable LEDAROOT is not set to the root directory of the LEDA system. 
\item \$LEDAROOT/Manual/cmd is not part of your PATH.
\item \$LEDAROOT/Manual/tex is not part of your TEXINPUTS.
\end{itemize}
\begin{verbatim}
                      LEDAROOT
    _____________________|______________________                      
   |       |      |               |             |
 incl   Cweb   Noweb            Lweb          Manual
   |                                        _____|_______________
 LEDA                                      |     |        |      |
                                          cmd   noweb    tex  MANUAL
                                                               |
                                                              DVI
                                                              
                                                             
\end{verbatim}
shows the parts of the LEDAROOT directory relevant for manual production
and documentation. The include directory contains all header files of the 
LEDA system, the directories Cweb, noweb, and Lweb contains examples
of full documentation written with various literate programming tools,
and Manual contains all the relevant commands and tex files.

The Lman utility can be applied to LEDA data types and user-defined 
data types.
Write \\ 
\verb-Lman T[.h] options -
to apply it to the LEDA data type T and
write\\
\verb-Lman T[.ext] options - to apply it to file T.ext in the working directory. The extensions lw (Lweb file), nw (noweb file), w (a Cweb-file), and h (h-file) are possible. The extensions are tried in this order and the working directory is searched before the LEDA include directory. The following options are available:
\smallskip\\
size={12,11,10}\\
constref={no,yes}\\
partypes={no,yes}\\
usesubscripts={no,yes}\\
numbered={no,yes}\\
xdvi={yes,no}\\
warnings={yes,no}\\
ack={yes,no}\\
latexruns={1,2,0}\\
filter={all,signatures,definition,creation,operations,implementation,example,opname}\\
pid={"",string}

Options are given in assignment syntax. There must be no blank on either side of the equality sign.

The size-option selects the
font-size. The option constref determines whether const-ref pairs are shown, 
the option partypes determines whether the type of a value parameter of
an operator is suppressed if equal to the currently defined type, and
the option usesubscripts determines whether indexed variables are typeset 
using subscripts.  

A manual page can be numbered or not and the call of xdvi can be suppressed.
Lman may be asked to issue warnings and warnings may require a user action or
not. We recommend to run Lman with \verb-warnings=yes- and \verb-ack=yes-
in the early stages of designing a manual page.
Lman usually runs \LaTeX\ twice in order to get cross-references correct.
You may settle for a single run of \LaTeX. Lman makes use of a preprocessor
called ext. The preprocessor writes its output on file /tmp/pid-ext.tex
where pid is either the process identification of the preprocessor run or
specified by the pid-option. Mkman makes use of the pid-option. You will probably never have to use it. 

There are four ways to specify options for Lman. You may either put them 
into the file itself by means of the Moptions command, or you can put them
onto the command line, or you can put them into a configuration file
Lman.cfg in either the working directory or the home directory.

The Lman-utility can also be told to extract only part of a manual page by
the filter-option. The options definition, 
creation, operations, implementation, and example cause extraction of the 
corresponding section of the manual, and the option signatures
extracts the signatures of all operations but suppresses the descriptions.
One can also extract a single operation by using its name, e.g., \verb-Lman stack filter=push- extracts the push operation of the
stack type 
and \verb-Lman point filter=operator+- extracts the + operator of the point
type (write arrop to inquire about the array operator and funop to inquire
about the function operator). 

Fman is an alternative to Lman. It gives low quality ASCII output but works faster.

Mkman is the tool to produce manuals like the LEDA manual. 

Ldoc is the utility that supports the production of full documentations. All remarks above apply equally well to Ldoc. Ldoc applies to Lweb, noweb, and Cweb files. For use with noweb and Lweb, the LEDA dialect of noweb, you must have installed noweb and for use with Cweb you must have installed Cweb. The subdirectories Cweb, noweb, and Lweb contain full documentations of parts of the LEDA system. Copy a file from one of these directories to your working directory and run Lman on it to see it in action. If it does not work check whether you have installed the proper literate programming system. 
 
Lweave is the weave tool for Lweb.



\section{Introduction}

The production of manual pages and full documentations proceeds in phases.
\begin{verbatim}

Lman:

XXX.[h|lw|nw|w]  ----->  XXX.tex   -------> XXX.dvi
                 ext.pl             latex


lweave and lw2dvi:

XXX.lw ---------->  XXX.tex -------> XXX.dvi
         lweave              latex


Ldoc:

XXX.[lw|nw|w] ----> temp.[lw|nw|w] --------------> XXX.tex -------> XXX.dvi
  |           ext.pl               [lw|no|c]weave       |   latex
  | ext.pl                                              |
  |                                                     |
XXX.man ------------------------------------------------
                   \input


Fman:

XXX.[h|lw|nw|w]  ----------> ASCII
                    Fman

\end{verbatim}
We use standard tools for all but the first phase. The first phase is accomplished by the perl program \emph{ext.pl}. It
realizes Lman, Ldoc and Fman in a very direct way.

<<Lman>>=
perl $LEDAROOT/Manual/cmd/ext.pl Lman $*

<<Ldoc>>=
perl $LEDAROOT/Manual/cmd/ext.pl Ldoc $*

<<Fman>>=
perl $LEDAROOT/Manual/cmd/ext.pl Fman $1 $2

<<lextract>>=
#!/bin/csh -f
set infile = $1
set outfile = $2
shift
shift
perl $LEDAROOT/Manual/cmd/ext.pl Mkman $infile outfile=$outfile $*


<<Mkman>>=
#!/bin/csh -f
if ($1 == "") then
  set source = $LEDAROOT/incl/LEDA
  set ext = h
else 
  set source = $1
  if ($2 == "") then
    set ext = h
  else
    set ext = $2
  endif
endif

\rm -r -f extract

mkdir extract

echo Extracting manual pages ...
echo " "

foreach f ($source/*.$ext)
   echo "extracting manual from $f"
   lextract $f  extract/`basename $f .$ext`.tex
end


<<Mkdvi>>=
#!/bin/csh -f
if ("$cwd" != "$LEDAROOT/Manual/MANUAL") then
  echo " "
  echo "must be executed in directory MANUAL"
  echo " "
  exit
endif
if ($1 == "") then
  set source = $LEDAROOT/incl/LEDA
  set ext = h
else 
  set source = $1
  if ($2 == "") then
    set ext = h
  else
    set ext = $2
  endif
endif

\rm -r -f DVI

mkdir DVI
cd DVI

echo Making dvi-files for manual pages ...
echo " "

foreach f ($source/*.$ext)
   echo "preparing dvi-file for manual page for $f"
   Lman $f xdvi=no dvioutfile=`basename $f .$ext`.dvi

end
cd ..

@ LEDAROOT is an environment variable that must be set to the LEDA root
directory; see the LEDA installation instructions for details. 

\begin{figure}
{\footnotesize
\begin{verbatim}
\documentclass[12pt,a4paper]{article}
\input MANUAL.pagesize
\input MANUAL.mac

\begin{document}
\begin{manual}
 
\section*{Stacks(stack)}\label{stack}

\definition

An instance $S$ of the parameterized data type \mbox{$\mathit{stack<E>}$} is a sequence of 
elements of
data type $E$, called the element type of $S$. Insertions or deletions of elements 
take place only at one end of the sequence, called the top of $S$. The size of $S$ 
is the length of the sequence, a stack of size zero is called the empty stack. 


\creation

\create {\mbox{$\mathit{stack\<E\>}$}}
{\mbox{$\mathit{S}$}} 
{creates an instance \mbox{$\mathit{S}$} of type \mbox{$\mathit{stack\<E\>}$} and initializes it to the empty stack. 
}

\setlength{\typewidth}{2.5cm}
\setlength{\callwidth}{4cm}
\computewidths
\operations

\function {\mbox{$\mathit{E}$}}
{\mbox{$\mathit{S.}$}top\mbox{$\mathit{()}$}} 
{returns the top element of \mbox{$\mathit{S}$}.\\ \precond $S$ is not empty. 
}

\function {\mbox{$\mathit{void}$}}
{\mbox{$\mathit{S.}$}push\mbox{$\mathit{(E\ x)}$}} 
{adds $x$ as new top element to \mbox{$\mathit{S}$}. 
}

\function {\mbox{$\mathit{E}$}}
{\mbox{$\mathit{S.}$}pop\mbox{$\mathit{()}$}} 
{deletes and returns the top element of \mbox{$\mathit{S}$}.\\ \precond $S$ is not empty. 
}

\function {\mbox{$\mathit{int}$}}
{\mbox{$\mathit{S.}$}empty\mbox{$\mathit{()}$}} 
{returns true if \mbox{$\mathit{S}$} is empty, false otherwise. 
}

\end{manual}
\end{document}
\end{verbatim}
}% end footnotesize
\caption{The intermediate Tex-file for the example of Figure 1.2 in \cite[Chapter Manual Pages and Documentation]{LEDA-Buch}}
\label{intermediate tex-file}
\end{figure}

Figure \ref{intermediate tex-file} shows the intermediate \TeX-file produced by Lman for the data type stack shown in Figure \ref{}. 
The TeX file basically contains one TeX-macro call for each manual command. It also has a short preamble and postamble. The preamble reads MANUAL.pagesize and MANUAL.mac, opens the document and enters the manual environment, and the postamble closes the manual environment and the document. The files MANUAL.pagesize and MANUAL.mac are both contained in the LEDAMAN directory; they contain the definition of the pagesize used for the LEDA manual and the definition of the manual macros respectively. 

Ldoc applied to the same file produces (in stack.man) the subfile starting with
\verb-\begin{manual}- and ending with \verb-\end{manual}-. Ldoc also produces a temporary file temp.w which is obtained from the input file by deleting all manual comments. It applies cweave to this file to obtain XXX.tex. 

<<MANUAL.pagesize>>=
%the following settings are adequate for European size a4 paper
\textwidth 16cm  
\textheight 24 cm  
\topmargin -14mm    
\evensidemargin 3mm 
\oddsidemargin 3mm
%the following settings are adequate for US legal size paper
%\textwidth 16cm  
%\textheight 24 cm  
%\topmargin -14mm    
%\evensidemargin 3mm 
%\oddsidemargin 3mm
\sloppy	

<<MANUAL.mac>>=
<<manual environment>>
<<special symbols>>
<<items and such>>
<<header lines>>
<<widths>>
<<functions>>
<<constructors and destructors>>
<<old macros>>

@
\section{The Manual Environment}

The manual environment redefines some basic parameters of LaTeX, namely
parskip, parindent, and baselineskip.
parskip governs the vertical space between paragraphs and parindent governs
indentation at the beginning of a paragraph. In LaTeX the first quantity is
zero and the second quantity is non-zero. The TeX file of Figure \ref{intermediate Tex file} consists of many short paragraphs, each paragraph being basically a LaTeX command. We therefore want no indentation
but we want paragraphs to be separated. baselineskip controls the vertical distance between lines. We increase its value slightly.

When leaving the manual environment we set all values back to their original values. This requires no code in LaTeX. When used in Ldoc this has the effect of using the parameter settings below for the manual and to use the standard Cweb settings for the remainder of the document.

<<manual environment>>=
\newenvironment{manual}{
\baselineskip 3.0ex     % was 14pt about 1/5in = 0.5cm
%\spaceskip  .4em plus .25em minus .25em
%\xspaceskip .65em
\parskip 11pt plus 1pt minus 1pt
\parindent 0pt
}% the manual style
{}% There is nothing to do when I leave the environment

@ 
\section{Ext: An Overview }

Ext.pl operates in phases. The first phase processes the command line, takes care of initialization, and produces the preamble. The second phase does most of the work. It reads the input file and 
produces the body of a TeX-file.
The third phase adds the postamble and calls cweave and/or latex. In Ldoc-mode the third phase also removes all 
With the option mode=Mkman ext carries out only the first two phases, 
the resulting file can then be included in some larger document, and
with the option Fman ext produces ASCII-output on standard output.

The production of ext's output is controlled by the so-called manual comments
in the input file, see the chapter on Manual Production in the LEDA-book
for further details. You must be familiar with that chapter in order
to understand this program.

The details of the behavior of ext are directed by options. The options
are processed in the initialization phase of ext.


<<ext.pl>>=
<<required packages>>

<<command line processing and initialization>>
<<main program>>
<<generate postamble and call LaTeX or Cweb>>

<<subroutines>>

@
\section{Command Line Processing and Initialization}


<<command line processing and initialization>>=
<<determine mode and set options to default values>>
<<determine actual options and derived variables>>
<<set up input and output files>>
<<generate preamble>>

@
The first argument tells ext whether it works for Lman, Ldoc, Fman or Mkmanual. If ext receives only one argument it prints usage information for
its first argument, see section \ref{usage}. We have a variable for each option. The variables are initialized to their default values.

<<determine mode and set options to default values>>=

$mode = $ARGV[0] && shift;

if (!($ARGV[0])) { &print_usage($mode);}
    
$filearg = $ARGV[0] && shift;

if ($mode eq "Mkman") { $numbered = "yes"; }
else { $numbered  = "no";}      # Usually manual pages are not numbered
$ack = "yes";            # ext asks for acknowledgments when it is confused
$constref = "no";   # const-& pairs are usually suppressed
$partypes = "no";   # operators suppress argument types that are identical to Mname
$usesubscripts = "no";    # usually we do not write indexed variables as subscripts
$size = 12;             # default size is 12pt
$xdvi = "yes";
$warnings = "yes";     # default is to give warnings
$filter = "all";        # usually we show everything
$print_title = 1;  # usually we print the title
$pid = "";            # we do not know the process id yet
$latexruns=1;
$map = "";           # the substitution map
$delman = "yes";     # Ldoc usually removes manual comments
$outfile = "";       # the default is that we determine the outfile
$dvioutfile = "";     # only relevant for Mkdvi
$section = "section"; # each manual page is a LaTeX section 
$nextwarning = "yes"; # default is to show the next warning
$justset = "no";      # $nextwarning was not just set to no.



@ In Fman-mode there is only one further argument, the filter. In the other 
modes we look for options in the file \$mode.cfg 
in the home directory or in the working directory or on the command line. Later
options take precedence.

The variable \$pid is set to the process id of the current process (available in variable \$\$) if the user leaves it undefined.

We use a derived variable \$showsem. 

<<determine actual options and derived variables>>=

if ($mode eq "Fman")
{ if ($ARGV[0]) 
    { $filter = $ARGV[0];    
      foreach  $candidate ("all","signatures","definition","creation",  
              "operations","implementation","example")
        { if ($filter eq $candidate) { goto filterfound; }
        }
      print "\n\n searching for operation $filter of type $filearg";
      filterfound:
      } 
  print "\n\n\n"; 
}
else
{ foreach $path ("HOME","PWD")
  { if ($path eq "HOME") {$CFG = $ENV{$path} . "\/" . $mode . "\.cfg";}
    else {$CFG = $mode . "\.cfg";}
    if (-e $CFG)
     { open (CFG); 
       print "reading ", $CFG,"\n\n";
       while (<CFG>) 
         { if (/(\w+)=(.*)/) {eval "\$$1 = \$2";} 
         }
       close (CFG);
     }
  }
  eval "\$$1 = \$2" while $ARGV[0] =~ /(\w+)=(.*)/ && shift; 
}

if ($pid eq "") {$pid = $$;}

$showsem = 1;          # usually we show the semantics of functions
 if ($filter eq "signatures")
  { $filter = "operations";
    $showsem = 0;
  }

@

We set up the various input and output files. We set\\
[[$LEDAROOT]] to the LEDA root directory
[[$INCL]] to the directory containing all LEDA header files,\\ 
[[$basename]] to the file argument minus the extension (if any),\\
[[$INPUT]] to the input file ( either [[$basename.[lw|w|nw|h]]] in the working directory or
[[$basename.h]] in the LEDAINCLUDE directory,\\
[[$kind]] to the kind of the input file,\\
[[OUTPUT]] to /tmp/\$pid-ext.tex.

If we are in Lman-mode, want to use xdvi, and the dvi-file exists already
we simply call xdvi. This is for quick access to the LEDA manual.

<<set up input and output files>>=

$LEDAROOT = $ENV{"LEDAROOT"};
$INCL = $ENV{"LEDAROOT"} . "/incl/LEDA";
if ($filearg =~ /(.*)\.[whln]/)
  {$basename = $1;}
else
  {$basename = $filearg;}

@doc_tools = ('Lman','Ldoc','Fman','lweave','lw2dvi');
foreach $arg (@doc_tools)
  { if ($basename eq $arg)
      {  $owd = $ENV{"PWD"};
         chdir ("/tmp");
         if ($mode eq "Fman") 
          { system("cat \$LEDAROOT/Manual/MANUAL/doctools.tex");
          }
         else
          { $outfile = "/tmp/" . $pid . "-ext.tex";
            open(OUTPUT,">".$outfile);
            print OUTPUT "\\documentclass\[11pt,a4paper\]\{article\}\n\n"; 
            print OUTPUT "\\input " . $ENV{"LEDAROOT"} . "/Manual/tex/MANUAL.pagesize\n\n";
            print OUTPUT "\\input " . $ENV{"LEDAROOT"} . "/Manual/tex/MANUAL.mac\n\n"; 
            print OUTPUT "\\begin\{document\}\n\n";
            close(OUTPUT);
            system("cat \$LEDAROOT/Manual/MANUAL/doctools.tex  >> $outfile");
            open(OUTPUT,">>".$outfile);
            print OUTPUT "\\end\{document\}\n\n";
            close(OUTPUT);
            system ("latex /tmp/$pid-ext.tex");

            system ("xdvi /tmp/$pid-ext.dvi");
          }
        chdir ("$owd");
        exit;
      }
  }
if (-e ($basename . "\.w")) 
  { $INPUT = $basename . "\.w" ; $kind = "Cweb"; $ext = "w";goto DONE;}
if (-e ($basename . "\.web")) 
  { $INPUT = $basename . "\.web" ; $kind = "Cweb"; $ext = "web";goto DONE;}
if (-e ($basename . "\.lw")) 
  { $INPUT = $basename . "\.lw" ; $kind = "Lweb";$ext = "lw"; goto DONE;}
if (-e ($basename . "\.nw")) 
 { $INPUT = $basename . "\.nw" ; $kind = "noweb"; $ext = "nw";goto DONE;}
if (-e ($basename . "\.h")) 
 { $INPUT = $basename . "\.h" ; $kind = "h";goto DONE;}
$longname = $INCL . "/" . $basename;
if (-e ($longname . "\.h"))
 { $INPUT = $longname . "\.h" ; $kind = "LEDAtype";}
DONE:
open (INPUT)  || die "ext: Cannot find input file $basename: $!\n";

if ($mode eq "Lman" && $xdvi eq "yes" && 
      (-e "$LEDAROOT/Manual/MANUAL/DVI/$basename.dvi"))
  { print "\n\ndvi-file exists already and so Lman takes a shortcut\n\n";
    system("xdvi $LEDAROOT/Manual/MANUAL/DVI/$basename.dvi");
    exit;
  }    

if ($mode ne "Fman") 
  { if ($outfile eq ""  || $mode eq "Ldoc") 
           {$outfile = "/tmp/" . $pid . "-ext.tex";}
    open(OUTPUT,">".$outfile);
    print "reading input file to extract manual ...\n\n";
  }

@

Having opened all files we now construct the preamble. For Lman it has the form

\begin{verbatim}
\documentclass[$size pt,a4paper]{article}
\input MANUAL.pagesize
\input MANUAL.mac
\begin{document}
\begin{manual}
\end{verbatim}

For Ldoc and Mkman we only need to generate \verb-\begin{manual}-.


<<generate preamble>>=

if ($mode eq "Lman")
{  
                            
  print OUTPUT "\\documentclass\[" . $size . "pt,a4paper\]\{article\}\n\n"; 

  print OUTPUT "\\input " . $ENV{"LEDAROOT"} . "/Manual/tex/MANUAL.pagesize\n\n";

  print OUTPUT "\\input " . $ENV{"LEDAROOT"} . "/Manual/tex/MANUAL.mac\n\n"; 

  print OUTPUT "\\begin\{document\}\n\n";

  print OUTPUT "\\begin\{manual\}\n\n";                        
}
if ($mode eq "Ldoc" || $mode eq "Mkman") {print OUTPUT "\\begin{manual}\n";}

@
\section{Ext: The Main Loop}
\subsection{Overview}

We now come the core of ext. It is a single while loop that scans the input
for manual commands. Whenever a manual command is encountered the appropiate 
output is produced.

We need to recall some facts. The output actions of ext are directed
by manual comments, i.e., comments starting with \verb-/*{\M- and
ending with \verb-}*/-. Many of these comments refer to the preceeding
code unit. A code unit is any maximal contiguous sequence of non-empty lines
not containing any line belonging to an Mcomment. We call a line starting with
\verb-/*{\M- an Mline.

Three placeholders are relevant for manual production:\\
Mvar = the name of the canonical variable.\\
Mtype = the short type name, defined in the header of the manpage\\
Mname = the full type name, i.e., Mtype if there are no type parameters and 
Mtype$\langle$par\_list$\rangle$ if there are type parameters. 
The default value of all three placeholders is the empty string.

<<main program>>=
$Mvar    = "";
$Mtype   = ""; 
$Mname   = "";
main_loop:
{ # $_ is either undefined or the last line of an Mcomment
  <<determine code unit>>
  # $_ is an Mline and variables $original_code_unit and $code_unit 
  # contain the current code unit. 
  <<determine manual comment and manual command>>
  # $Mcomment contains the manual command (without the brackets /*{\M and }*/
  # $Mcommand contains the command (without the leading M)
  <<process manual comment>>
redo main_loop;
}

@
\subsection{Building a Code Unit}

We build up a code unit by reading lines until we encounter an empty line
or an Mline. We skip empty lines. If the
first nonempty line is an Mline we have found a code unit that requires action.
Otherwise, we discard the current code unit and use the non-empty line as the first line of our next attempt.

Cweb inputs require some additional care. We ignore all lines starting with 
\verb-@s- or \verb-@f-.




<<determine code unit>>=
# I advance $_ to a non-empty line (WEB-directives are output but count as 
# empty lines otherwise) or beyond the end of the file

$_ = <INPUT>;

build_code_unit:
    while ($_ && (($_ =~ /^\s*$/) || ($_ =~ /^\@[sf]/))){  $_ = <INPUT>; }
    if (! $_) {last main_loop;}   # input exhausted
    $code_unit = "";
    # $_ exists, is non_empty, and contains no @, and $code_unit is empty
    # The code_unit is either terminated by an Mcomment or an empty line
    # (empty line: only white space characters) or the end of the file
    while ($_ && !(/\/\*\{\\M/ || /^\s*$/)) 
     { if ($_ =~ /\/\* *\{M/)
         {&print_warning("I encountered /*{M. Did you really mean it?");}     
       $code_unit .= $_;   # append current line to code unit
       $_ = <INPUT>;
     }

# The current line either does not exist or is either empty or the 
# begin of an Mcomment.
# Skip empty lines.

while ( $_ && /^ *$/ ){ $_ = <INPUT>; }

# the current line is non-empty (if it exists).

if (! $_) {last main_loop;}   # input exhausted

# the current line is non-empty.

if (! (/\/\*\{\\M/)) { goto build_code_unit;}   # start new code unit.

@invisible_words = ('__exportC' , '__exportF' , '__exportD');
foreach $invis_word (@invisible_words)
  { $code_unit =~ s/$invis_word//g;
  }

$original_code_unit = $code_unit;

@
\subsection{Reading a Manual Comment}

The current line contains the begin of an Mcomment. I first
remove the \verb-/*{\- and everything preceeding it
and then process a command.
Processing a command entails the following:
Production of the required output and moving the current line to the
last line of the manual comment.
In order to make life simple I concatenate the comment into a single string.

<<determine manual comment and manual command>>=

s/^(.*)\/\*\{\\//; # remove begin comment and everything before it

if ($1 =~ /\S/) # issue warning if something non-white before comment
 { &print_warning("ignored non-white stuff in front of begin comment\n"); }

$Mcomment = "";

while ($_ && (! ( /\}\*\// ) ) )
{
if (/\} *\*\//) {&print_warning("encountered } */ in manual comment. Did you mean }*/ ?");}
$Mcomment .= $_;
$_ = <INPUT>;
}
if (! $_){die "ERROR: missing end comment\n";}


s/\}\*\/(.*)$/ /;  # replace end comment and everything after it by a blank
if ($1 =~ /\S/)
  { &print_warning("ignored non-white after Mcomment."); }

$Mcomment .= $_;   
$original_comment = $Mcomment;

# Mcomment contains the entire manual comment. We extract the command (the
# maximal alphanumeric prefix).

$Mcomment =~ /^(\w*)\W.*/;
$command = $1;
$Mcomment =~ s/$command *//;  # remove command and succeeding blanks
$command =~ s/^M//;           # remove the M

@
\subsection{Processing a Manual Command}

At this point we have completely read a manual comment. We have 
the command (without the leading M)
available in [[$command]] and we have the remainder of the comment available in 
[[$Mcomment]]. We process commands in a big case statement with one case for each manual
command. 

There is one command that requires special treatment, the Moptions command
that turns off warnings for the next command. We use variables \$nextwarning
and \$justset to deal with them. We initialize the first variable to yes
and the second variable to no. Whenever we process a nextwarning=no in Moptions
we set nextwarning to no and justset to true. The justset is changed back to no
before the next command is processed. This makes sure that nextwarning applies 
exactly to the next command. 
pront\_warning does not print if nextwarning is no.

<<process manual comment>>=
if ($nextwarning eq "no" && $justset eq "no") { $nextwarning = "yes";} 
$justset = "no";
switch: 
{ if ($command eq 'options') {<<options>> last switch;}
  if ($command eq 'subst')   {<<subst>> last switch;}

  if ($command eq 'anpage') {<<Manpage command>> last switch;}
  if ($command eq 'definition' || $command eq 'example'  
            || $command eq 'implementation' || $command eq 'creation' ||
               $command eq 'operations')
     {<<definition etc.>> last switch;}
  if ($command eq 'text'  || $command eq "preamble")
     {<<text or preamble>> last switch;}

  <<commands for manual entries>>
&print_warning( "did not recognize command name M" . $command);
}

@ We now come to the various manual commands. They fall naturally into three groups:
Moptions and Msubst produce no output, Manpage, Mdefinition, Mexample, Mimplementation,
Mcreation, Moperations, Mtext and Mpreamble only deal with text, and all others need to extract code from the preceding code unit.

@ \section{Moptions}

The comment is a single options. We first remove leading and trailing
white stuff (= all space characters) and then proceed as on command line.

<<options>>= 
$Mcomment =~ s/\s//g;
$Mcomment =~ /^(\w+)=(.*)$/ ;
eval "\$$1 = \$2";
if ($nextwarning eq "no") {$justset = "yes";}

@ \section{Msubst}

The comment is a sequence of lines each containing a pair w1 w2. We put them
into [[$map]].

<<subst>>= 
while ($Mcomment =~ s/ *(\w+) +(\w+) *//) {$map{$1} = $2;}
 
@ \section{The Manpage command}

Mcomment is equal to $\{$type$\}\ \{$par\_list$\}\ \{$title$\}\ \{$varname$\}$
where the last argument is optional. We extract the parts, define the values
of the placeholders, and produce the header line of
the manual page. The header line is not produced if ext works for Ldoc. 

<<Manpage command>>=
if (! ($Mcomment =~ /\{([^\{\}]*)\}\s*\{([^\{\}]*)\}\s*\{([^\{\}]*)\}\s*\{([^\{\}]*)\}/ || 
       $Mcomment =~ /\{([^\{\}]*)\}\s*\{([^\{\}]*)\}\s*\{([^\{\}]*)\}/ ) )                         
  { &print_warning("Manpage expects either three or four arguments"); }
$Mtype = $1;
$par_list = $2;
$title = $3;
if ($4) {$Mvar = $4;}
if ($par_list =~ /^ *$/) {$Mname = $Mtype;}
else 
  { # remove excessive blanks in parlist
    $par_list =~ s/ //g;
    $Mname = $Mtype."<".$par_list.">";
   } 
if ($mode eq "Lman" || $mode eq "Mkman")
  { 
    # we print \section*{title (type')}\label{type}\n where type' is obtained
    # from type by quoting underscores.
    # if numbered is true we supress the star
    $Mtype1 = $Mtype;
    $Mtype1 =~ s/_/\\_/g;
    if ($numbered eq "yes") {$star = "";} else {$star = "*";}
    print  OUTPUT "\\$section" , $star, "{",$title," (",$Mtype1,
              ")}\\label{",$title,"}\n\\label{$Mtype}\n";
   }

 
@
\section{The Mdefinition, Mcreation, Moperations, Mexample and Mimplementation commands}

We come to the commands for the header lines of the various parts of
a manual page. The body of these commands is either text or defines some
widths and/or placeholders. We proceed in steps:

\noindent
Step 1:\\
Mcreation: determine varname and declwidth. Set [[$Mcomment]] to empty string.\\
Moperations: determine typewidth and callwidth. Set [[$Mcomment]] to empty string.\\
All others: Do nothing\\
Step 2: Store [[$Mcommand]] in [[$currentsection]]\\
Step 3: Produce output. The output consists of a backslash, followed by the command name,
followed (if there is text) by a newline followed by the text. The text is subject to placeholder substitution and
conversion from C to LaTeX. This is the task of procedure [[convert_text]]. In Fman mode
we only perform placeholder substitution.

<<definition etc.>>=
if ($command eq "creation")
{ # Mcomment may contain a varname and/or a length.
  @params = split(' ',$Mcomment);  # split at blanks
  foreach $i (0 .. $#params)
   { if ($params[$i] =~ /^[a-zA-Z]/) 
       { $Mvar = $params[$i];}    # variable names start with a letter
     else
       {  $a = $params[$i];
          if ($a =~ /^ *$/) {print "something wrong in create";}
          if ($a =~ /^[0-9\.]*$/) {$a = $a . 'cm';}
          print OUTPUT "\\setlength\{\\declwidth}\{" , $a, "\}\n" ;
          print OUTPUT "\\computewidths\n";
       }
    }
  $Mcomment = "";
}

if ($command eq "operations")
{ # Mcomment is either empty or a b where a and b are lengths
  # If the lengths are without dimension then we add cm

  @params = split(' ',$Mcomment);  # split at blanks
  foreach $i (0 .. $#params)
    {  $a = $params[$i];
       if ($a =~ /^[0-9\.]*$/) {$a = $a . 'cm';}
       if ($i == 0)
         { print OUTPUT "\\setlength\{\\typewidth\}\{" , $a, "\}\n" ;}
       else { print OUTPUT "\\setlength\{\\callwidth\}\{" , $a, "\}\n" ;} 
    }
  print OUTPUT "\\computewidths\n";
  $Mcomment = "";
}

$currentsection = $command;

if ($filter eq "all" || $filter eq $currentsection)
{ if ($mode eq "Fman")
    { print $command , "\n______________\n\n" , &substitute_for_placeholders($Mcomment) 
             ,"\n\n"; }
   else 
     { $output = "\\" . $command ;
       if ($Mcomment) { $output .= "\n" . &convert_text($Mcomment);}
       &print_unit($output);
     }
}
      
@ \section{Mtext and Mpreamble}

This is basically the third step of the previous section. However, in Ldoc mode we produce no output for Mpreamble. 

<<text or preamble>>=
      
if ($filter eq "all" || $filter eq $currentsection )
 { if ($mode eq "Fman")
       { print &substitute_for_placeholders($Mcomment) , "\n\n"; }
   else 
       { if ($command eq "text" || $mode ne "Ldoc")   
           { &print_unit(&convert_text($Mcomment)); }
       }
 }

@ It is natural to learn about functions [[convert_text]] and [[print_unit]] at this point.

<<subroutines>>=
sub print_unit{
   local($text) = @_; # read argument into local variable
   print OUTPUT $text,"\n\n";
}

@ \section{Converting Bodies of Manual Commands to \LaTeX}

Many manual comments contain pieces of text. We prepare this text for output
in a two step process. 
We first subject it to placeholder substitution (procedure [[substitute_for_placeholders]] and 
then to \CC to \LaTeX\ conversion (procedure [[web_to_latex]].

The result of this process is not for human consumption. We found that even some programs have difficulties with it because it may contain lines of 200 and more characters. Latex has no problems with this but cweave does. We therefore break the output at suitable blanks.

<<subroutines>>=
sub convert_text{
  local($text) = @_; # read argument into local variable
  $text = &substitute_for_placeholders($text);
  $text = &web_to_latex($text);
  if ($kind eq "Cweb")
    { <<break into reasonable length lines>> }
  $text;
}

<<break into reasonable length lines>>=
  
local($i, $remline, $outline, $lines , $word); 
@lines = split(/^/,$text);  # split at new lines
$text = "";
foreach $i (0 .. $#lines)
  {if (length($lines[$i]) > 80)
     { $outline = "";
       $remline = $lines[$i];
       while ($remline )            
         { if ($remline =~ /[\w\,] /) 
             {  $word = $` . $&; $remline = $';}
           else {$word = $remline; $remline = ""; }
           # a word charachter or komma followed by a blank or the entire line
           if (length($outline) + length($word) < 80)
             {$outline  .= $word;}
           else 
             {if ($outline) { $text .= $outline . "\n"; }
              else { &print_warning("unable to break line, might cause trouble with cweave\n$word\n\n");}
              $outline = $word;
             }
          }
       $text .= $outline;   # no newline here
      }
   else { $text .= $lines[$i]; }   # no newline here
 }  

@ \subsection{Placeholder Substitution}

We define a function that replaces all occurences of the placeholders
Mvar, Mtype, and Mname by the values of the corresponding variable. Some 
users prefer to drop the M in all placeholders. We warn them. We also replace the keys in
the substitution map.

<<subroutines>>=

sub substitute_for_placeholders{
  local($string) = @_;
  $string =~ s/\\Mvar/$Mvar/g;
  $string =~ s/\\Mtype/$Mtype/g;
  $string =~ s/\\Mname/$Mname/g;
  foreach $key (keys(%map))  # for each key  in the substitution map
     { $string =~ s/$key/$map{$key}/g; }
  
  if ($string =~ /\\var\W/ || $string =~ /Mvar/) {&print_warning("found an occurrence of \\var or an unslashed occurrence of Mvar. Did you mean \\Mvar?");}
  if ($string =~ /\\type\W/ || $string =~ /Mtype/) {&print_warning("found an occurrence of \\type or an unslashed occurrence of Mtype. Did you mean \\Mtype?");}
  if  ($string =~ /\\nameW/ || $string =~ /Mname/) {&print_warning("found an occurrence of \\name or an unslashed occurrence of Mname. Did you mean \\Mname?");}

  $string;
}

@ \subsection{Web to latex}  


[[web_to_latex]] takes any string and applies [[convert_line]] to each line
of the string.

<<subroutines>>=
sub web_to_latex{
  local($text) = @_; # read argument into local variable
  local($output) = "";
  while ($text)
    { $text =~ /^([^\n]*\n)/;
      $text = $';
      $output .= &convert_line($1);
    } 
    return $output;
}

<<conversion subroutines>>



@ \section{Constructors, Destructors, and Operations}

All commands to follow generate output for the current code unit.
We therefore need to parse the current code unit. It is supposed to 
contain the 
definition or declaration of a single function or operator. 
The result of the parse will be made available in the following varables:\\
[[$type]] contains the return type.\\
[[$fname]] is the name of the function.\\
[[$signature]] is what we usually set in the second column.\\
[[$prefix]], [[$funcname]], [[$postfix]] are a detailed version of the signature. [[$funcname]] is what appears in roman in the LEDA manual.\\
[[$constructor]], [[$static]], [[$operator]], [[$conversion]], [[$destructor]] record if
the code unit contains a special function.\\

We generate a manual entry in two steps. We first parse the code unit and thus
determine the values of all variables below. In a second step we actually generate the entry.

<<commands for manual entries>>=
$prefix = "";
$funcname = "";
$postfix = "";
$signature  = ""; 
$type = "";
$fname = "";
$static = 0;
$constructor = 0;
$operator = 0;
$conversion = 0;
$destructor = 0;

if (! $code_unit)
  { &print_warning("current code unit is empty."); 
    last switch;
  }
<<parsing the code unit>>
<<producing the manual entry>>

@
\subsection{Parsing the Code Unit}

A (standard) function definition or declaration have the following form:
A possibly empty list of qualifiers (static, extern, friend, inline,
virtual) and a return type separated by blanks (if the return type is 
missing it is taken to be int)\\
the function name (a function name is a string over a-zA-Z\_0-9.
(HOW ABOUT ::?) or it has the form operator opsymbol)\\
a (\\
a possibly empty list of parameters separated by comma\\
a )\\
the optional qualifier const\\
a semicolon or a compound statement.\\

\noindent
Among the qualifiers only static has an effect on the output.
\smallskip

\noindent
If the function is a constructor we may have a list of constructor calls
after the closing bracket, i.e.,\\
a :\\
followed by a sequence of function calls seperated by comma.
\smallskip

\noindent A destructor has the format $\sim$Mtype().
\smallskip

\noindent
The syntax of type conversion functions is different, namely
\verb-operator typname-. There are no brackets.

A code unit is supposed to consist of a single function definition 
or declaration. We allow to stretch this rule a bit in order to 
allow a more natural mode of expression. 
\begin{itemize}
\item The code unit may be a comment. In this case it must start 
with /* and end with */ both on 
separate lines. The first line may contain a text.
\item The code unit may contain more than one function definition. 
This is either used for closely related functions or for functions 
that have a conditional definition. I remove the compiler 
directives (starting with \# followed by letters) and then
extract the \emph{last} definition as follows. We search for a innermost 
matching pairs of 
parenthesis (pattern \verb-\{[^\{\}]*\}-) and replace it by a 
semicolon. We proceed until there are no pairs left. At this point we have a 
sequence of function definitions, each followed by a semicolon. 
The last function definition is the one after the next to last semicolon.  
\end{itemize}

A code unit may contain Cweb-directives. We remove them first.
 
<<purging code unit from formatting instructions>>=
$code_unit =~ s/\@\+/ /g; # remove @+
$code_unit =~ s/\@\// /g; # remove @/
$code_unit =~ s/\@\|/ /g; # remove @|
$code_unit =~ s/\@\#/ /g; # remove @#
$code_unit =~ s/\@\;/ /g; # remove @;
$code_unit =~ s/\@\,/ /g; # remove @,



<<parsing the code unit>>=
  
<<purging code unit from formatting instructions>>

if ($code_unit =~ /\/\*/)       # commented code units
  { &print_warning("code unit contains a comment. I remove the lines containing /* and */");
    $code_unit =~ s/ *\/\*.*//;  # remove first line
    $code_unit =~ s/ *\*\/ *//;    # remove last line
    $original_code_unit = $code_unit;
  }
$code_unit =~ s/\t/ /g;        # replace tab by blank
$code_unit =~ s/ *\#.*\n/ /g;  # remove all lines with compiler directives 
$code_unit =~ s/\n/ /g;       # replace newline characters by blanks
while ($code_unit =~ s/\{[^\{\}]*\}/\;/) {}  
             # replaces code by a single semicolon.
while ($code_unit =~ s/\;\s*\;/\;/) {}        
             # replaces white space-separated ; by a single ;
$code_unit =~ s/\; *$//;                   
             # remove last semicolon if only followed by whitespace
if ($code_unit =~ /\;([^\;]*)$/)
     { &print_warning("code unit contains several function definitions. I extracted\n $1");
       $code_unit = $1;
     }

# At this point we have a single function definition in code_unit
   
$code_unit =~ s/const *$//;  # remove const qualifier
$code_unit =~ s/::/doppeldoppel/g;  # replace :: by doppeldoppel
$code_unit =~ s/ *:.*$//;    # remove initialization constructor call
$code_unit =~ s/doppeldoppel/::/g;   # reintroduce ::
# $code_unit =~ s/; *$///;    # remove ;blanks at end of line

@ The code unit should now end with a ) maybe followed by blanks (if the
function is a conversion function there will be no )
We next work at the beginning of the code unit. We first remove 
a template definition \verb-template< class T>- and then all
qualifiers. If we find a static qualifier we record that fact.

<<>>=
$code_unit  =~ s/template *< *class *\w* *>// ; # remove template definition
$code_unit  =~ s/virtual//;  # remove blanks virtual blanks      
$code_unit  =~ s/friend//;       # remove friend
$code_unit  =~ s/inline//;       # remove inline
$code_unit  =~ s/extern//;       # remove extern
$static = ($code_unit  =~ s/static//);  #remove static and record

@ At this point we have the form\\
\begin{tabular}{ll} 
type fname ( parlist )            & for a standard function\\
type operator opsymbol (parlist ) & for the definition of an operator\\
Mtype ( parlist )                 & for a constructor\\
operator type                     & for a conversion function.\\
$\sim$Mtype ()                  & for a destructor.\\
\end{tabular}

\noindent
In either case we define signature as fname(parlist).\\

\noindent
We collect information to distinguish cases. We have a conversion operator 
if there is no (), an operator if operator is present but we are not 
in the conversion case, a destructor if the code unit starts with ~,
and a constructor or member function otherwise.

<<>>=
$conversion = ! ($code_unit =~ /\(/); 
if ($code_unit =~ /\( *\) *\(.*\)/) { $code_unit =~ s/\( *\) *\((.*)\)//; }
else { $code_unit =~ s/\((.*)\)//;}

$par_list = $1;

$operator = (($code_unit =~ /operator/) && !$conversion);  # symbol operator

$destructor = ($code_unit =~ /^ *\~/);
 
&remove_enclosing_blanks($code_unit); # I do anchored matches below

extraction:
{ if ($destructor) {last extraction;}
 
  if ($conversion)     # a conversion function: operator type
    { if (!($code_unit =~ s/ *operator *//))
        {&print_warning("expected a conversion function")};
      $fname = $code_unit;
      last extraction;
    }

  if ($operator)  # an operator: type operator opsymbol  
   { $code_unit =~ /^(.*) *operator *(.*)$/;
     $type = $1;
     $fname = $2;
     last extraction;
   }
 <<constructor and proper function>>
}    
@ The case of a standard function or constructor remains: 
a standard function is of the form type fname where 
fname is of the form (class name::)*name
I postulate that fname contains no blank and hence fname is
everything after the last blank 
note that type may be empty and that type may bracketed by const \&
A constructor has the form $\sim$Mtype.

Cweave taught me that life is more complex than this.\\
\verb+array<rat_vector>linear_base()+\\
is apparently perfect \CC. I think it's sick but I have to handle it anyhow.

If the code unit matches Mtype then I have a constructor. Otherwise the 
function name is the maximal suffix that consists only of word characters and colons. If this is everything the return type is integer. If it is not everything then the return type is the remainder (but without trailing blanks).


<<constructor and proper function>>=
if ($code_unit eq $Mtype) {$constructor = 1;}
else
  { # a function
    if ($code_unit =~ /^([:\w]+)$/ )
      { $type = "int";
        $fname = $code_unit;
      }
    else 
      { $code_unit =~ /^(.*[^\:\w])([\:\w]+)$/ ;
        $type = $1; 
        $fname = $2;
        $type =~ s/ //g;  # remove blanks
        if (($type =~ /^\s*const/) 
              && ($constref eq "no"))  # remove const & bracket
          { $type =~ s/^\s*const//; $type =~ s/\& *//;
          }
        $type =~ s/ *\& */\& /g;
       }
   }

        
<<old code>>= 
 if ($code_unit =~ /^(.*) +([^ ]+)$/)
    { $type = $1; 
      $fname = $2;
      if (($type =~ /^\s*const/) && ($constref eq "no"))  # remove const & bracket
         { $type =~ s/^\s*const//; $type =~ s/\& *//;
         }
      $type =~ s/ *\& */\& /g;
    }
   else # return type is empty or constructor
    { if ($code_unit =~ /$Mtype/)
        { $constructor = 1; }
      else {
        $type = "int";
        $fname = $code_unit;
        }
    }


@ \subsection{Generating a Manual Entry}

Now that we parsed the code unit we can proceed to generate output.
We prepare type, fname, varname, and par\_list for output and  
define signature as fname(parlist). 

It is helpful to remove leading and trailing blanks from all relevant variables.

<<producing the manual entry>>=
&remove_enclosing_blanks($type);
&remove_enclosing_blanks($fname);
&remove_enclosing_blanks($Mvar);
&remove_enclosing_blanks($Mtype);
&remove_enclosing_blanks($command);

@ In par\_list we remove const \& pairs and rebuild par\_list with one blank
after each comma. We also remove blanks before \&.

Well, this is not quite right. I do not want a blank before the  second comma in
\verb|...,sortseq<K,I> S,...|

<<>>=
@params = split(/,/,$par_list);  # split at commas
$par_list = "";
$i = 0;
while ($i <= $#params)
{ $j = $i + 1;
  while ($params[$i] =~ /</  && (($params[$i]=~tr/</</) > ($params[$i]=~tr/>/>/)))
    { $params[$i] .= "," . $params[$j]; $j++;
    }
  if (($params[$i] =~ /^ *const/) && ($constref eq "no"))
     { $params[$i] =~ s/^ *const//;
       $params[$i] =~ s/\& */ /; # replace &blanks by a single blank
     }
  &remove_enclosing_blanks($params[$i]);
  $params[$i] =~ s/ *\& */\& /g;
   
  if ($i > 0) {$par_list .= "\, ";}
  $par_list .= $params[$i];
  $i = $j;
}

$varname = $Mvar;
$signature = $fname . "(" . $par_list . ")";

if ($command =~ /^opl?$/){<<Mop>> last switch;} 
   
if ($command =~ /^funcl?$/) {<<Mfunc>> last switch;}
  
if ($command =~ /^binopl?$/) {<<Mbinop>> last switch;}
  
if ($command =~ /^binopfuncl?$/) {<<Mbinopfunc>> last switch;}
 
if ($command =~ /^arropl?$/) {<<Marrop>> last switch;}
  
if ($command =~ /^funopl?$/) {<<Mfunop>> last switch;}
  
if ($command =~ /^unopl?$/) {<<Munop>> last switch;}
       
if ($command =~ /^unopfuncl?$/){<<Munopfunc>> last switch;}
        
if ($command =~ /^staticl?$/){<<Mstatic>> last switch;}
     
if ($command =~ /^conversion/){<<Mconversion>> last switch;}
     
if ($command =~ /^create/){<<Mcreate>> last switch;}
 
if ($command =~ /^destruct/) {<<Mdestruct>> last switch;}

 
@ \subsubsection{Mop}

<<Mop>>=
if ($operator || $constructor || $conversion || $static)
     {&print_warning("Mop applies only to member functions and not to operators, ...");}

$prefix = $Mvar . "\.";
$funcname = $fname;
$postfix = $par_list;
if ($filter eq "all" || $filter eq $currentsection || $filter eq $funcname)
  { &print_function();}

@ \subsubsection{Mfunc}

<<Mfunc>>=
if ($operator || $constructor || $conversion || $static)
     {&print_warning("Mop applies only to functions and not to operators, ... ");}

$prefix = "";
$funcname = $fname;
$postfix = $par_list;
if ($filter eq "all" || $filter eq $currentsection || $filter eq $funcname )
  { &print_function(); }
     
@
\subsubsection{Binary Operators as Members}
The operator name is available in fname, the first argument is
Mvar, and the second argument is par\_list. Everything else is as below.

<<Mbinop>>=
if (! $operator) {&print_warning("Mbinop applies only to operators");}

$Mreplace = $Mname . " ";

if ($partypes eq "no")
   { while ($par_list =~ /$Mreplace/) {$par_list = $` . $';} }    

$signature = $Mvar. " " . $fname . " " . $par_list;

if ($filter eq "all" || $filter eq $currentsection ||
        $ filter eq ("operator" . $fname) ){&print_function();}

@ \subsubsection{Binary Operators as Non-Members}

fname contains the operator symbol
and par\_list contains the arguments. 
We replace the comma in par\_list by fname surrounded by blanks.

<<Mbinopfunc>>=
if (! $operator) {&print_warning("Mbinopfunc applies only to operators");}
 
$Mreplace = $Mname . " ";

if ($partypes eq "no")
     { while ($par_list =~ /$Mreplace/) {$par_list = $` . $';} }        

$par_list =~ s/\, / $fname /;

$signature = $par_list;
    
if ($filter eq "all" || $filter eq $currentsection || 
        $ filter eq ("operator" . $fname) ){&print_function();}

@ \subsubsection{Array Operator}

par\_list contains a single element.

<<Marrop>>=
if (! $operator) {&print_warning("Marrop applies only to operators");}

$signature = $varname . "\[" . $par_list . "\]";

if ($filter eq "all" || $filter eq $currentsection
         || $filter eq "arrop" ){&print_function();}

@ \subsubsection{Function Operator}

<<Mfunop>>=
if (! $operator) {&print_warning("Mfunop applies only to operators");}

$signature = $varname . "\(" . $par_list . "\)";

if ($filter eq "all" || $filter eq $currentsection || 
         $filter eq "funop" ){&print_function();}

@ \subsubsection{Unary Operator as Member}

The operator is availabe in fname.
 \verb|++| and \verb|--| come in postfix and prefix. The postfix operators have
 an integer argument.
new and delete have arguments and are prefix.
\verb|->| is postfix .
<<Munop>>= 
    
if (! $operator) {&print_warning("Munop applies only to operators");}
     
unopcases:
  {if ($fname eq "->")
        {$signature = $varname . $fname;   # -> is postfix
         last unopcases;
        }
   if ($fname eq "new" || $fname eq "delete" )
        { $signature = $fname . ' ' . $varname;  # new and delete are prefix
          last unopcases;
        }
   if ($par_list)
         {$signature = $varname . $fname; # postfix ++ and --
          last unopcases;
         }       
   $signature = $fname . $varname; # all others are prefix operators 
  }

if ($filter eq "all" || $filter eq $currentsection ||
         $filter eq ("operator" . $fname )){&print_function();}

@ \subsubsection{Unary Functions as Non-Members}

The operator is availabe in fname.
 \verb|++| and \verb|--| come in postfix and prefix. The postfix operators have
two arguments,
new and delete have arguments and are prefix.
\verb|->| is postfix .

     
<<Munopfunc>>=
if (! $operator) {&print_warning("Munop applies only to operators");}
     
unopfunccases:
 {if ($fname eq "->")
        {$signature = $varname . $fname;   # -> is postfix
         last unopfunccases;
        }
  if ($fname eq "new" || $fname eq "delete" )
        { $signature = $fname . ' ' . $varname;  # new and delete are prefix
          last unopfunccases;
        }
  if ($par_list =~ /,/)
         {$signature = $varname . $fname; # postfix ++ and --
          last unopfunccases;
         }       
  $signature = $fname . $varname; # all others are prefix operators 
}

if ($filter eq "all" || $filter eq $currentsection ||
         $filter eq ("operator" . $fname ) ){&print_function();}

@ \subsubsection{Static Member Functions}
For static member functions the fname is Mtype::fname.

<<Mstatic>>=
if (!$static) {&print_warning("Mstatic applies only to static member functions");}
     
$prefix = $Mtype . "\:\:";
$funcname = $fname;
$postfix = $par_list;
     
if ($filter eq "all" || $filter eq $currentsection || $filter eq $fname )    
    {&print_function();}

@ \subsubsection{Conversion Operators}

We have the type to be converted
to in fname. A conversion call is fname(Mvar).

<<Mconversion>>=
if (!$conversion) {&print_warning("Mconversion applies only to conversion operators");}

$funcname = $fname;
$postfix = $Mvar;
     if ($filter eq "all" || $filter eq $currentsection ){&print_function();}

@ \subsubsection{Constructors}

Mcomment is Ltext at this point. A constructor call is Mtype(par\_list).

<<Mcreate>>=
if (!$constructor) {&print_warning("Mcreate applies only to constructors");}

if ($filter eq "all" || $filter eq $currentsection ){&print_constructor();}

@ \subsubsection{Destructors}

Mcomment is Ltext at this point. A destructor call is $\sim$Mtype().

<<Mdestruct>>=

if (!$destructor) {&print_warning("Mdestruct applies only to destructors");}

if ($filter eq "all" || $filter eq $currentsection ){ &print_destructor();}


@ \subsection{Printing the entry for a function}

[[print_function]] prints the manual entry for a function. It makes use of the 
global variables command, type, prefix, funcname , postfix, and Mcomment. We have

\begin{verbatim}
               prefix    funcname     postfix          signature           return type
Mop            Mvar.      fname        par_list                            yes
Mfunc                     fname        par_list                            yes
Mstatic        Mtype::    fname        par_list                            yes
Mconversion               fname        Mvar                                no

Mbinop                                               Mvar op  par_list     yes
Mbinopfunc                                           arg1 op arg2          yes
Marrop                                               Mvar[arg]             yes
Mfunop                                               Mvar(par_list)        yes
Munop                                                the right thing       yes
Munopfunc                                            the right thing       yes
  
\end{verbatim} 

We output\\
\verb-\function {return type} {prefix funcname} {postfix} {Mcomment}- in the first four cases and \\
\verb-\operator {return type} {signature} {Mcomment}- in the other cases.

There is a subtlety in the first case. We want funcname to be printed in roman. Thus web to latex conversion is only applied to the prefix and not to funcname. In funcname we only quote underscores.

We need to apply the substitution map to all elements of funcname, prefix, \ldots. We use
the following construction. We create a list [[@args]] of relevant quantities.
We cycle through the list ann apply the substitution map to each element of the
list.

<<subroutines>>=

sub print_function{
@args = ("funcname","prefix","postfix","signature","type");
foreach $arg (@args)
{ foreach $key (keys(%map)) 
     {$$arg =~ s/$key/$map{$key}/g; }
} 
if ($mode eq "Fman")
 { if ($funcname) {$signature = $prefix . $funcname . "(". $postfix. ")";}
   print $type , " ", $signature , "\n" ;
   if ($showsem == 1) 
   { print &substitute_for_placeholders($Mcomment) , "\n\n"; }
   return;
 }

$arg1 = "";  # conversion functions have no return type
$arg4 = "";  # description may be empty

if ($type) { $arg1 = &convert_M($type);}

$arg2 = "";
if ($funcname)
  { if ($prefix) { $arg2 .= &convert_M($prefix);}
    $funcname =~ s/_/\\nspaceunderscore\\_/g;  # quote and back up slightly
    $arg2 .= $funcname;
    if ($postfix =~ /^ *$/) {$arg3 = "";}
    else {$arg3 = &convert_M($postfix);}
   }
else
  { $arg2 =   &convert_M($signature);
    $arg3 = "";
  }

if ($Mcomment && $showsem == 1) {$arg4 = &convert_text($Mcomment);}
 
local($text) = "";
if ($command =~ /^opl?/ || $command =~ /^funcl?/ || $command =~ /^staticl?/)
 {  if ($arg3 eq "") {$arg3 = "\$\\,\$"; } # small space
    $text = "\\function" .' {'. $arg1 . "\}\n\{". $arg2 ."\} \n\{". $arg3 . "\} \n\{" . $arg4 .'}';
 }
else 
 { $text = "\\operator" .' {'. $arg1 . "\}\n\{". $arg2 ."\}  \n\{" . $arg4 .'}'; }

print OUTPUT $text,"\n\n";

}

@ \subsection{Printing a Constructor}

We output
\verb-\create {Mname} {Mvar} {par_list} {Mcomment}-

<<subroutines>>=
sub print_constructor{
@args = ("par_list");
foreach $arg (@args)
   { foreach $key (keys(%map)) 
     {$$arg =~ s/$key/$map{$key}/g; }
   } 
if (!$Mvar || !$Mname )
     {&print_warning("ERROR: You forgot to define either Mvar or Mname");}
if ($mode eq "Fman")
    { $signature = $Mname . " " . $Mvar;
      if ($par_list) { $signature .= "(" . $par_list. ")"; }
      print $signature , ";\n" , &substitute_for_placeholders($Mcomment) , "\n\n";
      return;
    }
$arg1 = &convert_M($Mname);
$arg2 = &convert_M($Mvar);
if ($par_list)
    { $arg3 = &convert_M($par_list);}
else
    { $arg3 = "";}  # empty arg list
  
$arg4 = &convert_text($Mcomment);

local($text) = "\\create" .' {'. $arg1 ."\}\n\{". $arg2 ."\} \n\{".$arg3 . "} \n\{".$arg4 .'}';

print OUTPUT $text,"\n\n";

}

@ \subsection{Printing a Destructor}

We output
\verb-\destruct {Mname} {Mcomment}-

<<subroutines>>=
sub print_destructor{

 if ($mode eq "Fman")
 { print "~", $Mname ,"()\n" , &substitute_for_placeholders($Mcomment) ,"\n\n";
 }

  $arg1 = &convert_M($Mname);
     
  $arg2 = &convert_text($Mcomment);

  local($text) = "\\destruct" .' {'. $arg1 ."\}\n\{". $arg2 ."\}\n";

  print OUTPUT $text,"\n\n";
}

@ \section{TeX Macros that typeset functions, operators, constructors and destructors}

We define and initialize some width parameters that are used in the commands that typeset manual entries and then turn to the actual typesetting.

\subsection{Some width variables}
We define several length variables. These variables define the width of the various columns in the layout of the creation and the operations sections. The separation between columns is colsep. 

The layout for the creation-section uses the variables 
createtextwidth and declwidth, where\\ 
createtextwidthwidth = textwidth - declwithwidth. We use two-column
layout if the length of the declaration is at most declwidth minus colsep, and use
two-row layout otherwise.

The layout of the operations-section uses the variables typewidth, callwidth, longcallwidth, and descriptwidth, where\\
longcallwidth = textwidth - typewidth     and\\
descriptwidth = textwidth - typewidth - callwidth 
We use three-column layout if the width of the call is at most callwidth and
use two-row layout otherwise. Again we make sure that the colums are separated by colsep.

Manual entries for variables and constructors are separated by entrysep and
the two rows of an entry in two-row layout are separated by rowsep.
The default values are set as percentages of textwidth or as relative length.
I hope that this will allow to use different font sizes and page sizes.
  
<<widths>>=
\newlength{\rowsep} \setlength{\rowsep}{0.7ex} %separation in two-row layout

\newlength{\entrysep} \setlength{\entrysep}{0.5ex} %additional pace between entries

\newlength{\colsep} \settowidth{\colsep}{\ }    

\newlength{\typewidth} \setlength{\typewidth}{0.15\textwidth}    

\newlength{\callwidth} \setlength{\callwidth}{.25\textwidth}      

\newlength{\declwidth} \setlength{\declwidth}{0.25\textwidth}  

\newlength{\longcallwidth}
\newlength{\descriptwidth}
\newlength{\createtextwidth}
\newlength{\textminusdescriptwidth}
\newlength{\typepluscallwidth}

\newcommand{\computewidths}  
        {
          \setlength{\createtextwidth}{\textwidth}
          \addtolength{\createtextwidth}{-\declwidth}             

          \setlength{\longcallwidth}{\textwidth} 
          \addtolength{\longcallwidth}{-\typewidth}

         \setlength{\descriptwidth}{\textwidth}
         \addtolength{\descriptwidth}{-\typewidth}
         \addtolength{\descriptwidth}{-\callwidth} 

         \setlength{\textminusdescriptwidth}{\textwidth}
         \addtolength{\textminusdescriptwidth}{-\descriptwidth}

         \setlength{\typepluscallwidth}{\typewidth}
         \addtolength{\typepluscallwidth}{\callwidth}
       }

\def\setopdims #1 #2   {\typewidth=#1cm
                        \callwidth=#2cm
                        \computewidths
                        }


\computewidths    % initializes all widths

@ \subsection{Operations}

We have two macros to typeset entries for functions and operators:\verb-\function-
and \verb-\operator-. The second is a simplified version of the first and thus we discuss
\verb-\function-. It has four arguments, the return type, the fname, the parameter list and the description. We need to make layout decisions based on the length of the various parameters. The if-then package comes handy to program the case distinction.

Both commands use the LaTeX parbox command extensively. In particular, in
two-row layout I generate a parbox for each row and also put the two
rows into a parbox. Since parboxes are symbols this has the effect of
disallowing page breaks between the two rows.

We start out by checking the equation 
\verb-\typewidth + \callwidth + \descriptwidth = \textwidth-. It is easy to violate it without noticing. This produces strange layouts. I have once spent hours to discover the error.

Our layout strategy is as follows. Assume first that the actual width of the return type plus colsep is larger than typewidth. Consider \verb-#1 #2(#3)-. This is the return type plus the function call. If its width plus colsep is larger than the width alloted for the first two columns we use two row layout and otherwise we use one row layout. In the first case it may even be the case that the function call does not fit into a single line. We therefore compute the width of \verb-#1 #2(-. This is assumed to fit into a line. We put it down and use the remaining width for the parameter list plus ).

<<functions>>=
\usepackage{ifthen}
\newlength{\actualcallwidth}
\newlength{\actualtypewidth}
\newlength{\actualtypepluscallwidth}
\newlength{\fnamewidth}
\newlength{\checkwidth}

\newcommand{\function}[4] 
   {\setlength{\checkwidth}{\typewidth}   
   \addtolength{\checkwidth}{\callwidth}
   \addtolength{\checkwidth}{\descriptwidth}
   \ifthenelse{\lengthtest{\checkwidth = \textwidth}}
              {}
              {\typein{WARNING: The invariant 
\typewidth + \callwidth + \descriptwidth = \textwidth is violated. 
Did you change one of the quantities without calling
\protect\computewidths? I do it for you. If the output looks okay
and you changed textwidth after reading in Lweb.sty it is safe to ignore
this warning. Type any character to proceed.}
\computewidths}

       \settowidth{\actualcallwidth}{#2(#3)}        
       \settowidth{\actualtypewidth}{#1}
       \addtolength{\actualcallwidth}{\colsep}
       \addtolength{\actualtypewidth}{\colsep} 
       \ifthenelse{\actualtypewidth > \typewidth}
       {%\typeout{WARNING: #1 is too long to fit into the box provided for the return type.}
        %\typein{\\Type anything to acknowledge.} 
        \settowidth{\actualtypepluscallwidth}{#1\ #2(#3)}
        \addtolength{\actualtypepluscallwidth}{\colsep}
        \ifthenelse{\actualtypepluscallwidth > \typepluscallwidth}
        {% begin then1
       \settowidth{\fnamewidth}{#1\ #2(}%
       \setlength{\parlistwidth}{\textwidth}%
       \addtolength{\parlistwidth}{-\fnamewidth}%
       \noindent
       \parbox[t]{\textwidth}{%
       \parbox[t]{\fnamewidth}{#1\ #2(}%
       \parbox[t]{\parlistwidth}{\raggedright \sloppy #3)}\vspace{\rowsep}\\%
       \hspace*{\typewidth}\hfill\parbox[t]{\descriptwidth}{\sloppy #4}%
       }%end big parbox       
       }%end then1
       {%else descript on same line
       \parbox[t]{\typepluscallwidth}{#1\ #2(#3)}%  
       \parbox[t]{\descriptwidth}{\sloppy #4}%
       }% end else descript on same line 
       }% end return type does not fit
       {% else return type fits                      
       \ifthenelse{\actualcallwidth > \callwidth}
      {\settowidth{\fnamewidth}{#2(}%
       \setlength{\parlistwidth}{\longcallwidth}%
       \addtolength{\parlistwidth}{-\fnamewidth}%
       \noindent
       \parbox[t]{\textwidth}{%
       \parbox[t]{\typewidth}{#1}\parbox[t]{\fnamewidth}{#2(}%
       \parbox[t]{\parlistwidth}{\raggedright \sloppy #3)}\vspace{\rowsep}\\%
       \hspace*{\typewidth}\hfill\parbox[t]{\descriptwidth}{\sloppy #4}%
       }%end big parbox       
      }%end then
      {
       \noindent\parbox[t]{\typewidth}{\fussy #1}%
       \parbox[t]{\callwidth}{\raggedright \sloppy  #2(#3)}%\hspace{\colsep} 
       \parbox[t]{\descriptwidth}{\sloppy #4}%
      }%end else
      }%end retrun type fits
       \vspace{\entrysep}
       \par
       }

\newcommand{\operator}[3] 
      {%\smallskip
       \settowidth{\actualcallwidth}{#2} 
       \settowidth{\actualtypewidth}{#1}
       \addtolength{\actualcallwidth}{\colsep}
       \addtolength{\actualtypewidth}{\colsep} 
       \ifthenelse{\actualtypewidth > \typewidth}
       {%\typeout{WARNING: #1 is too long to fit into the box provided
%for the return type. I adopt another layout style. }
        %\typein{\\Type anything to acknowledge.}
        \settowidth{\actualtypepluscallwidth}{#1\ #2}
        \addtolength{\actualtypepluscallwidth}{\colsep}
        \ifthenelse{\actualtypepluscallwidth > \typepluscallwidth}
        {\parbox[t]{\textwidth}{%
       \parbox[t]{\textwidth}{#1\ #2}\vspace{\rowsep}\\%
       \hspace*{\textminusdescriptwidth}\parbox[t]{\descriptwidth}{\sloppy #3}%
       } %end big parbox
       }
       {%else descript on same line
       \parbox[t]{\typepluscallwidth}{#1\ #2}  
       \parbox[t]{\descriptwidth}{\sloppy #3}%
       }
       }
       {%else return type fits                     
       \ifthenelse{\actualcallwidth > \callwidth}
      {
       \noindent
       \parbox[t]{\textwidth}{%
       \parbox[t]{\typewidth}{\fussy #1}\parbox[t]{\longcallwidth}{\raggedright \sloppy #2}\vspace{\rowsep}\\%
       \hspace*{\textminusdescriptwidth}\parbox[t]{\descriptwidth}{\sloppy #3}%
       } %end big parbox
      }%end then
      {
       \noindent\parbox[t]{\typewidth}{\fussy #1}%\hspace{\colsep}
       \parbox[t]{\callwidth}{\raggedright \sloppy  #2}%\hspace{\colsep}%  
       \parbox[t]{\descriptwidth}{\sloppy #3}%
      }%end else
      }%end outermost else
       \vspace{\entrysep}
       \par
       }



@ \subsection{Constructors}

create has four arguments, the typename, the variable name, the parameter list and the text. We always put the text into a parbox of 
width createtextwidth. We measure the length of the 
declaration \verb-#1  #2;- or \verb-#1 #2(#3);- and use two-layout if the declaration 
is short. We use two-row layout otherwise. See the section on functions for more details.
 

<<constructors and destructors>>=
\usepackage{ifthen}
\newlength{\actualdeclwidth} \newlength{\parlistwidth}
\newcommand{\decl}{}
\newlength{\actualtypeplusnamewidth}

\newcommand{\create}[4] 
  {\setlength{\checkwidth}{\declwidth}   
   \addtolength{\checkwidth}{\createtextwidth}
   \ifthenelse{\lengthtest{\checkwidth = \textwidth}}
              {}
              {\typein{WARNING: The invariant \declwidth + \createtextwidth = \textwidth is violated. Did you change one of the quantities without calling
\protect\computewidths? I do it for you. If the output looks okay and you
changed textwidth after reading Lweb.sty it is safe to ignore this warning. Type any character to proceed.}
\computewidths}
   \ifthenelse{\equal{#3}{}}%
              {\renewcommand{\decl}{#1\ \ #2;}}%
              {\renewcommand{\decl}{#1\ \ #2(#3);}}%\typeout{decl is \decl}
   \settowidth{\actualdeclwidth}{\decl}
   \addtolength{\actualdeclwidth}{\colsep}
   \ifthenelse {\actualdeclwidth > \declwidth}
         {%\typeout{decl is long}
          \ifthenelse{\actualdeclwidth > \textwidth}
             {%\typeout{decl is very long}
              \settowidth{\actualtypeplusnamewidth}{#1\ \ #2(}%
               \setlength{\parlistwidth}{\textwidth}%
               \addtolength{\parlistwidth}{-\actualtypeplusnamewidth}%
               \parbox[t]{\textwidth}{%
               \parbox[t]{\actualtypeplusnamewidth}{#1\ \ #2(}%
                \parbox[t]{\parlistwidth}{\raggedright #3);}%
                \vspace{\rowsep}\\%
               \hspace*{1cm}\hfill\parbox[t]{\createtextwidth}{\sloppy #4}% 
                                      }%end parbox
             }
             {%\typeout{decl is long}
              \parbox[t]{\textwidth}{%
               \parbox[t]{\textwidth}{\decl}\vspace{\rowsep}\\%
               \hspace*{1cm}\hfill\parbox[t]{\createtextwidth}{\sloppy #4}% 
                                      }%end parbox
             }
       }%end then
       {%\typeout{decl is short}
\parbox[t]{\declwidth}{\decl}\parbox[t]{\createtextwidth}{\sloppy #4}%
       }%end else
  \vspace{\entrysep}\par
    }


@ \subsection{Destructors}

destruct has two arguments, the variable name followed by the text. We always put the text into a parbox of width createtextwidth. We measure the length of the destruction \verb-delete #1;- and use two-column layout if the destruction 
is short. We use two-row layout otherwise. 

<<>>=
\usepackage{ifthen}
\newlength{\actualdestructwidth}

\newcommand{\destruct}[2]
      { \settowidth{\actualdestructwidth}{$\sim$#1()}
        \ifthenelse {\actualdestructwidth > \declwidth}
           { \noindent
             \parbox[t]{\textwidth}{%
                 \parbox[t]{\textwidth}{$\sim$#1()}\vspace{\rowsep}\\%
                 \hspace*{1cm}\hfill\parbox[t]{\createtextwidth}{\sloppy #2}%
              } 
           }
           {\noindent\parbox[t]{\declwidth}{$\sim$#1()}%
            \parbox[t]{\createtextwidth}{\sloppy #2}%
           }
         \vspace{\entrysep}\par 
       }



@ \section{Postamble and Calling LaTeX and weave.}
The core of the output is produced at this point. We next generate the
postamble and then call weave and/or latex.

<<generate postamble and call LaTeX or Cweb>>=

if ($mode eq "Fman") {exit;}

if ($mode eq "Lman")
{ print OUTPUT "\\end\{manual\}\n";         
  print OUTPUT "\\end{document}\n";          
  close OUTPUT;
  $owd = $ENV{"PWD"};
  if ($latexruns == 0) {exit;}
  chdir ("/tmp");
   
  print "preparing  manual page with LaTeX  ...\n\n";

  if ($outfile ne "/tmp/$pid-ext.tex")
     { if ($outfile =~ /\//) # absolute path name 
          { system("cp $outfile /tmp/$pid-ext.tex");}
       else 
          { system("cp $owd/$outfile /tmp/$pid-ext.tex");}
      }

  system ("latex /tmp/" . $pid . "-ext.tex");
  if ($latexruns == 2) {system ("latex /tmp/" . $pid . "-ext.tex");}

  if ($xdvi eq "yes")
   { print "starting xdvi previewer ... \n\n";
     system ("xdvi -s 3 /tmp/" . $pid . "-ext.dvi");
   }
  else
   { if ($dvioutfile ne "")
      { print "\n\ncopying dvi file into file $dvioutfile in working directory\n\n";
        system("cp /tmp/$pid-ext.dvi $owd/$dvioutfile");
      }
     else 
      { print "\n\ncopying dvi file into file $basename.dvi in working directory\n\n";
     system("cp /tmp/$pid-ext.dvi $owd/$basename.dvi");
      }
   }

  # system("rm -f /tmp/" . $pid . "-ext.*");
  chdir ("$owd");
}

if ($mode eq "Mkman") {  print OUTPUT "\\end{manual}\n";}

if ($mode eq "Ldoc")
{  print OUTPUT "\\end{manual}\n";
   close(OUTPUT); 

  print "\n   created $basename.man\n\n\n";

  print "removing the manual comments (except for Mpreamble) from the input file ...\n\n";

  $tempfile = "/tmp/" . $pid . "-$basename";
  if ($delman eq "yes" || $kind eq "Cweb")
  { if ($delman eq "no")
      { print "option delman=no not implemented for Cweb\n";}
    system("ldel $INPUT $tempfile.$ext");
    print "\n    created $tempfile.$ext through ldel\n\n";

  }
  else { system("cp  $INPUT $tempfile.$ext"); 
         print "\n    created $tempfile.$ext by copying\n\n";
       }

   
  system("mv /tmp/$pid-ext.tex $basename.man");  # move manpage
  print "calling $kind weave ...\n\n";
  # cweave produces its output in the working directory
  # lweave produces its output in the directory of the input
  # noweave produces its output on standard output
  if ($kind eq "Cweb") 
     { system( "cweave $tempfile.$ext");
       system( "mv $pid-$basename.scn $basename.scn");
       system( "mv $pid-$basename.idx $basename.idx");
       system( "mv $pid-$basename.tex $basename.tex");

     }
  if ($kind eq "Lweb") 
     { system( "lweave $tempfile");
       system( "mv $tempfile.tex $basename.tex");
       system( "mv $tempfile.nw $basename.nw");

     }
  if ($kind eq "noweb") {system("noweave -delay $tempfile.nw > $basename.tex");}

  # system( "mv $tempfile $basename-del.$ext");
  print "\n   created $basename.tex\n\n\n";
  if ($latexruns == 0) {exit;}
  print "calling latex ...\n\n";
  system("latex  $basename.tex");
  if ($latexruns == 2) {system("latex  $basename.tex");}

  if ($xdvi eq "yes")
  { print "starting xdvi previewer ... \n\n";
    system("xdvi -s 3 $basename.dvi");
  }

}

@ In order to have access to the value of PWD we need to include the package
pwd.pl.

<<required packages>>=
require "pwd.pl";
&initpwd;

@ \section{Warnings and Error Messages}
Error\_handler and print\_warning prints the current line number, the error message,
and the current code unit and manual comment. If desired, both asks for
an acknowledgement. The output of the former functions cannot be turned off.

<<subroutines>>=
sub error_handler{
local($text) =  @_;  # read argument into local variable
print STDOUT "A problem occured near line " , $. ,"\n";
print STDOUT $text,"\n\n";
print STDOUT "The current code unit is:\n";
print STDOUT $original_code_unit, "\n";
print STDOUT "The current manual comment is:\n";
print STDOUT $original_comment, "\n\n";
if ($ack eq "yes") { print STDOUT "*  ";
            read(STDIN,$meaningless,1); }
}

sub print_warning{
if ($warnings eq "no" || $nextwarning eq "no") {return;}
local($text) =  @_;  # read argument into local variable
print STDOUT "A problem occured near line " , $. ,"\n";
print STDOUT "WARNING: ",$text,"\n\n";
print STDOUT "The current code unit is:\n\n";
print STDOUT $original_code_unit, "\n";
print STDOUT "The current manual comment is:\n\n";
print STDOUT $original_comment, "\n\n";
if ($ack eq "yes") { print STDOUT "*  ";
            read(STDIN,$meaningless,1); }
}

@ \section{Trivial Stuff}
The function remove\_enclosing\_blanks takes a 
string and removes all leading and trailing whitespace characters.
The perl notation for whitespace is \verb-\s-. It is equivalent to blank,
newline, carriage return, tab, and form feed. \verb-\S- is any non-whitespace
character. The pattern below relies on the fact that perl makes maximal
matches, i.e., the first \verb-\s*- matches a maximal prefix of 
whitespace characters.

<<subroutines>>=

sub remove_enclosing_blanks{
if ($_[0] =~ /^ *$/)  {$_[0] = "";}
else
  { 
    $_[0] =~ / *(.*[^ ]) *$/; 
    $_[0] = $1;   
  }
}


@ \section{Usage Information}

All utilities give manual information if called without arguments.

<<subroutines>>=

sub print_usage{
if ($mode eq "Lman" || $mode eq "Ldoc")
{ print "\n\n\n
usage is
         Lman|Ldoc file [options]
Options are given in assignment syntax variable=value. There must be no
blank on either side of the equality sign. We list all variables and 
their possible values below. For each variable the default value of 
each option is given first.

size={12,11,10}
constref={no,yes}
partypes={no,yes}
numbered={no,yes}
xdvi={yes,no}
warnings={yes,no}
ack={yes,no}
usesubscripts={no,yes}
latexruns={1,2,0}
delman={yes,no}
filter={all,signatures,definition,creation,operations,
implementation,example,opname}

Lman and Ldoc can be customized by putting options in a 
file Lman.cfg or Ldoc.cfg 
in either 
the home directory or the working directory.

Call Lman Lman or Lman Ldoc for more information.  

call\n\n\n";
}
if ($mode eq "Fman")
{ print "\n\n\n
usage is
         Fman file filter

where the file name is of the form T[.h/.w] and T is either 
the name of a LEDA type, e.g., list, sortseq, or point, or 
the name of a user defined data type. The value of filter is one of {all,signatures,definition,creation,operations,
implementation,example,opname}" ;
}
exit;
}


@ \section{Macros for Items and such}

<<items and such>>=
\def\CC{C\raise.08ex\hbox{\tt ++\ }}
\def\CCC{C\raise.08ex\hbox{\tt ++}}
\def\g++{g\hbox{\tt ++\ }} 
\def\nat{\hbox{\rm\vrule\kern-0.045em N}}
\def\real{\hbox{\rm\vrule\kern-0.035em R}}

\def\precond {{\it Precondition}: }
\def\Labs#1{\hbox{$|\,#1\,|$}}
\def\Lvert{|}
%\def\Litem#1{\hbox{{\tt <}$#1${\tt >}\ }}
\def\Litem#1{\hbox{$\langle #1 \rangle$}}
%I am not using the following anymore.
\def\sign{\mathop{\rm sign}}
\def\3{\ss{}}
\def\boxit#1{\vbox{\hrule\hbox{\vrule\kern3pt\vbox{#1}\kern3pt\vrule}\hrule}}
\def\co{\hbox{\tt //\ }}
\def\'{\hbox{\tt "}}
\def\'{^\prime}
\def\+{$+$}
\def\refsign{\hbox{\tt \&}}


@ \section{Macros for Header Lines}

The commands for header lines all have the same format. They typeset the
headerline in bold-face and put some stuff around it to control page 
breaks and distances. They disallow a pagebreak after the header 
line and encourage pagebreaks
before the header line. The empty line after the nopagebreak command is
crucial. It ensures that the text following the command is not in the same 
paragraph as the expanded command.



<<header lines>>=
\newcommand{\headerline}[1]
    {\smallskip\pagebreak[2]\par
     \parbox[t]{\textwidth}{{\bf #1}}\par
     \nopagebreak

    }%empty line is crucial 

\def\definition       {\headerline{1. Definition}}
\def\creation         {\headerline{2. Creation}}
\def\operations       {\headerline{3. Operations}}
\def\implementation   {\headerline{4. Implementation}}
\def\example          {\headerline{5. Example}}




@ \section{Old Macros}

Some of the stuff that follows can be purged.

<<old macros>>=
\def\Mdefinition       {{\bf $\backslash$ Mdefinition}\\}
\def\Mcreation         {{\bf $\backslash$ Mcreation}\\}
\def\Moperations       {{\bf $\backslash$ Moperations}\\}
\def\Mimplementation   {{\bf $\backslash$ Mimplementation}\\}
\def\Mexample          {{\bf $\backslash$ Mexample}\\}
\def\Mcreate           {{\bf $\backslash$ Mcreate}\\}

\def\Mop               {{\bf $\backslash$ Mop}        \hspace{1cm}}
\def\Mopl              {{\bf $\backslash$ Mopl}       \hspace{1cm}}
\def\Mbinop            {{\bf $\backslash$ Mbinop}     \hspace{1cm}}
\def\Marrop            {{\bf $\backslash$ Marrop}     \hspace{1cm}}
\def\Mfunop            {{\bf $\backslash$ Mfunop}     \hspace{1cm}}
\def\Munop             {{\bf $\backslash$ Munop}      \hspace{1cm}}
\def\Mfunc             {{\bf $\backslash$ Mfunc}      \hspace{1cm}}
\def\Mfuncl            {{\bf $\backslash$ Mfunc}      \hspace{1cm}}
\def\Mbinopfunc        {{\bf $\backslash$ Mbinopfunc} \hspace{1cm}}
\def\Munopfunc         {{\bf $\backslash$ Munopfunc}  \hspace{1cm}}




\def\If       {{\bf if} }
\def\Fi       {{\bf fi} }
\def\Then     {{\bf then} }
\def\Else     {{\bf else} }
\def\Do       {{\bf do} }
\def\Od       {{\bf od} }
\def\For      {{\bf for} }
\def\While    {{\bf while} }
\def\Return   {{\bf return} }
\def\Break    {{\bf return} }
\def\Continue {{\bf continue} }
\def\Case     {{\bf case} }
\def\Switch   {{\bf switch} }
\def\Class    {{\bf class} }
\def\Struct   {{\bf struct} }
\def\Public   {{\bf public} }
\def\Friend   {{\bf friend} }
\def\Typedef  {{\bf typedef} }

\def\n {\backslash n}



% LEDA macros:

\def\Forall         {{\bf forall} }
\def\Forallnodes    {{\bf forall\_nodes} }
\def\Foralledges    {{\bf forall\_edges} }
\def\Foralladjnodes {{\bf forall\_adj\_nodes} }
\def\Foralladjedges {{\bf forall\_adj\_edges} }


% verbatim

\font\ttbig= cmtt10 scaled \magstephalf

\chardef\other=12
\def\ttverbatim {
\parskip 5pt
\catcode`\&=\other \catcode`\{=\other \catcode`\}=\other
%\catcode'\\=\other 
\catcode`\$=\other \catcode`\&=\other
\catcode`\#=\other \catcode`\%=\other \catcode`\~=\other
\catcode`\_=\other \catcode`\^=\other
\obeyspaces \obeylines}


% usage:
%
%\begingroup
% \ttbig
% {\obeyspaces\gdef {\ }}
% \ttverbatim
%
% ...
%
%\endgroup

@ \section{The ldel command}

[[ldel infile outfile]] reads a file, deletes all manual comments from it (except Mpreamble comments) and
writes the output to outfile. 

<<ldel>>=
perl $LEDAROOT/Manual/cmd/ldel.pl $1 $2

<<ldel.pl>>=

<<subroutines>>

$INPUT = $ARGV[0] && shift;
$OUTPUT = $ARGV[0];

if ($OUTPUT eq "")
{print "usage

              ldel infile outfile              

removes manual comments from infile 
";
die;
}

open (INPUT)  || die "Can't find input file $INPUT: $!\n";
open(OUTPUT,">$OUTPUT");

    while (<INPUT>)
    { # The current line is either output or starts a manual comment
      $preamble = 0;
      if ( / *\/\*\{\\M/ )
      {  # current line contains the begin of a manual comment
         # we need to distinguish cases: if the manual comment is 
         # Mpreamble then we proceed as in the manual extraction and
         # otherwise we simply delete the manual comment.
         if ( s/ *\/\*\{\\Mpreamble// ) {$Mcomment = $_; $preamble = 1;}
         # we scan lines until we find the end of a manual comment
         while ($_ && (! ( /\}\*\// ) ) )
           { if ($preamble == 1) {$Mcomment .= $_;}
             $_ = <INPUT>; 
           }
         # the current line contains the end of a manual comment
         if ($preamble == 1) 
           { s/\}\*\/ *//; 
             $Mcomment .= $_;
             &print_unit(&convert_text($Mcomment));
           }
       }
       else { print OUTPUT $_; }
     }
  
close(OUTPUT);

@ \section{Lweave}
\subsection{Overview}

Lweave converts an Lweb file into a tex file. It operates in three phases

\begin{verbatim}

foo.lw -----> foo.nw --------------> temp.tex --------> foo.tex
       lw2nw         noweave -delay           emptyline

\end{verbatim}
The first phase takes care of unnamed code sections and quoted code and the third phase takes care of empty lines in code. The second phase calls noweave. The option delay means that we generate the preamble and postamble for LaTeX ourselves.

<<lweave>>=
#! /bin/csh
if (-e $1.lw) then
echo ""
echo "calling lw2nw"
echo ""
   lw2nw $1.lw > $1.nw
echo ""
echo "calling noweave -delay"
echo ""
   noweave -delay $1.nw > $1.temp

echo ""
echo "treating empty lines in code and taking care of pagebreaks"
echo ""
   emptyline $1.temp > $1.tex

else
echo ""
echo "file $1.lw does not exist"
echo ""
endif

<<lw2dvi>>=
#! /bin/csh
if(! (-e $1.lw)) then
echo " file $1.lw does not exist"
exit
endif

lweave $1

echo ""
echo "calling latex"
echo ""
latex $1.tex 

<<lw2nw>>=
perl $LEDAROOT/Manual/cmd/lw2nw.pl $1 

<<emptyline>>=
perl $LEDAROOT/Manual/cmd/emptyline.pl $1 

@ [[lw2nw.pl]] has  to deal with unnamed code sections and quoted code. 
An unnamed code section has the form 
\begin{verbatim}
 @c
 Zeile 1
   .
   .
   .
 Zeile n
 This empty line may or may not exist
 @ No comes text...
\end{verbatim}
I replace it by

\begin{verbatim}
\begin{Lcode}
[ [Zeile 1] ]
      .
      .
      .
[ [Zeile n] ]
\end{Lcode}
Jetzt kommt Text...
\end{verbatim}
where Lcode is a new environment. Lcode uses the corresponding noweb environment
and ensures proper spacing to the text above and below. Also I set codemargin to
parindent. This ensures that code and text is indented the same.

This must be in a style file.

<<Lweb.sty>>=

\usepackage{noweb}
\setlength{\codemargin}{\parindent}
<<redefinition of noweb parameters that control pagebreaks>>
\def\nwendcode{\endtrivlist \endgroup }
\nwcodepenalty=0 
\let\nwdocspar=\par%\filbreak 

<<MANUAL.pagesize>>
<<MANUAL.mac>>

\newcommand{\noeffect}{}

\newenvironment{Lcode}{%
\addtolength{\topsep}{-2.5ex}%
\@begincode  
}
{\endtrivlist
\vspace{0.5ex}  % Leerzeile ist wichtig??

}

@ Let us see the details of [[lw2nw.pl]]

In document chunks it applies [[convert_line]] to each line.

In unnamed program chunks it converts @c to begin\{Lcode\} and inserts the end\{Lcode\} at the end of the code. If there is an empty line at the end of the code I simply put it there. If there is no empty line I add it to the preceding line. In either case this does not corrupt the line count. 

Named code sections are converted to noweb style, i.e. @\< is replaced by \<\<
and @\> is replaced by \>\>. Also += is replaced by =. 

Noweave does not like \_ in junk names, although notangle handles them without any problems. I therefore quote underscores in junk names.



<<lw2nw.pl>>=

<<subroutines>>

$INPUT = $ARGV[0] && shift;

if ($INPUT eq "")
{print "usage

              lw2nw file              

Converts foo.lw to foo.nw. 
";
die;
}

open (INPUT)  || die "Can't find input file $INPUT: $!\n";

while (<INPUT>)
{  if (/^\@c/) # unnamed code section
    { # I read with one line lookahead because I want to remove empty lines 
      # at the end of codechunks.
      $_ = <INPUT>; $previous = "\\begin{Lcode}";           
      while (!/^\@\s/)
        { $current = $_;
          print $previous . "\n";
          chop($current);  # der reine Code ohne newline
          if ($current =~ /\<\<(.*)\>\>/)  # quote underscore in junk name
             {  $junk_name = $1;
                $cleft = $` . "<<";
                $cright = ">>" .$';
                $junk_name =~ s/_/\\_/g;
                $current = $cleft .$junk_name . $cright;
             }

          $previous =  "[[" .$current . "]]" ;          
          $_ = <INPUT>;
        }
      # current line starts text after code
      if ($previous =~ /[^\s\[\]]/) { print $previous . "\\end{Lcode}\n";}
      else { print "\\end{Lcode}\n"; }
    } # current line starts with @space (if condition applied)
   if (/^\@[\(\<](.*)\@> *\+ *=/)   # named code section: Cweb-style
     { $_ = "\<\<" . $1 ."\>\>=";}  # convert to Noweb style 
   if (/\<\<.*\>\>\+ *=/) {s/\+ *=/=/;}  
        # correct common mistake: replace >>+ = by  >>=
   if (/\<\<.*\>\>=/)
     { while (!/^\@\s/) 
        {  # I print line after treating applied occurrences
           # of Cweb-chunks
           s/\@\<(.*)\@\>/\<\<$1\>\>/;
           if (/\<\<(.*)\>\>/)  # quote underscore in junk name
             {  $junk_name = $1;
                $cleft = $` . "<<";
                $cright = ">>" .$';
                $junk_name =~ s/_/\\_/g;
                $_ = $cleft .$junk_name . $cright;
             }
           print; $_ = <INPUT>;
        }
     }
   # current line is a text line.
   print &convert_line($_);
}
close(<INPUT>);


@ \subsection{Procedure [[convert_line]]}

[[convert_line]] takes any string and applies C to LaTeX conversion to the
C-text contained in it. C-text may be enclosed between vertical bars,
in Mcode\{\ldots\}, between \DLK\ and \DRK\ brackets and in Tcode\{\ldots\}. 

We find the brackets and perform the appropriate conversion. [[convert_M] does the math-like conversion and [[convert_T]] does the typewriter-like conversion.

<<conversion subroutines>>=

sub convert_line{
  local($text) = @_; # read argument into local variable
  local($output) = "";
  chop($text);
iteration:
   while ($text)
    { if ($text =~ /^([^\\\[\|]+)/)  # does not start with [ or | or \
        { $text = $';
          $output .= $1;
          if ($text eq "") { last iteration;}
        } 
      # text is nonempty and starts with [ or | or \       
      if ($text =~ /^\\Mcode(.)/)
       { $text = $';
         $delimiter=$1;
         if (!($text =~ /\\$1/))  # \ to protext meta characters
            {&print_warning("Mcode extends beyond end of line");}
         $text = $';
         $output .= &convert_M($`);
         next iteration;
       }
      if ($text =~ /^\\Tcode(.)/)
       { $text = $';
         $delimiter=$1;
         if (!($text =~ /\\$1/))  # as above
           {&print_warning("Tcode extends beyond end of line");}
         $text = $';
         $output .= &convert_T($`);
         next iteration;
       }
      # next we deal with | in its exceptional meanings
      if ($text =~ /^\\begin\{tabular\}/)
       {  $output .= $text;
          last iteration;
       }     
      if ($text =~ /^\\left\|/)
       { $text = $';
         $output .= "\\left\|";
       }
      if ($text =~ /^\\right\|/)
       { $text = $';
         $output .= "\\right\|";
       }
      if ($text =~ /^\|/)
       { $text = $';
         if (!($text =~ /\|/)) { &print_warning("odd number of |:\n|$text\n\n");}
         $text = $';
         $output .= &convert_M($`);
         next iteration;
       }
      if ($text =~ /^\[\[/)
       { $text = $';
         if (!($text =~ /\]\]/))
           { &print_warning("encountered [[ without matching ]]:[[$text\n\n");}
         $code = $`;  
         $text = $';
         while ($code =~ /\]\]/)
           { $code = $`;
             $text = $' . "]]" . $text;
           }
         $output .= &convert_T($code);;
         next iteration;
       }
     
      # text does not start with a special symbol. Move first symbol to output.
      $text =~ /^(.)/;
      $output .= $1;
      $text = $';
    }
  return $output . "\n";
}
         
@ \subsection{Procedure [[convert_M]]}



Procedure \verb|convert_M| typesets \CC statements and returns \verb-\mbox{$\mathit{transformed text}$}-.
It is important to observe that this function makes no decisions about
spacing. They are made somewhere else. For example, we decided to have
a blank after each comma in a parameter list, but no blanks in type
parameter lists of templates. Also \& is sometimes a binary operator
and sometimes a unary operator. The decisions above require more
knowledge about the context than is available at this point. Hence all
these decisions are made somewhere else. 
The input is transformed according to the following rules:\\
quote all occurrences of \verb-&,%,_, ,<,>-, 
replace all occurrences of \verb-~- by \verb-\tildeop-, all occurences of 
\verb-^- by \verb-\circumflexop- all occurrences of 
\verb-@<<- by 
\verb-\ll-, all occurrences of \verb->>- by \verb-\gg-, and all occurences 
of :: by \verb-\DD-.

Some users like indexed variables to be written with subscripts. We provide
this feature as an option. We want to apply this transformation only
to variables consisting of a single character followed by a number.
We therefore search for the pattern [a-zA-Z][0-9]+, where the pattern
either occurs at the beginning of the string or after a nonword character.


We print the transformed string as  \verb-\mbox{$\mathit{transformed text}$}-. The purpose of the mbox-command is to put LaTeX into non-math mode at the
beginning of the C-Text and let it return to the original mode at the 
end of the Ctext. The net effect of the mbox command is no effect if 
the Ctext appears in ordinary mode and to erase the enclosing \$s if the 
Ctext appears in math-mode.

Change on April 4: The above strategy is to simple. I do not want to have the
entire text in mathitalics, e.g., in \verb-diff + 1- only diff should be in
math italics. I therefore change the strategy as follows. I output 
\verb-\mbox{$transformed text}$}-, where the transformed text contains all
identifiers in mathitalics. I also added one more layer of bracketing because
\verb|\Litem\mbox{   }| does not work.

One more difficulty with C-text is that the transformed test 
is a single long string. After all,
we quote blanks. This leads to difficulties with functions with long 
argument lists. I want to allow a line break after every comma and 
semicolon. To do so
I simulate the occurrence of two vertical bars after every comma or 
semicolon, in other words I replace ,blank by $|\ |$. This is only 
implemented for commas at the moment.

UBERPRUEFE DAS AUSSEHEN VON ++ und anderer Operatoren.
new und delete wird seltsam gesetzt.

<<conversion subroutines>>=

# the following procedure is copied from ext.nw. Please make changes only here.
# I still need  way to maintain consistency with ext.

sub convert_M{
 local($Ctext) = @_; # read argument into local variable
   # we first work on identifiers 
   local($prefix) = "";
   local($suffix) = $Ctext;
   local($ident) = "";
identloop:
   while ($suffix =~ /^(\W*)(\w.*)$/)
     { $prefix .= $1;
       $suffix = $2;
       if ( $suffix =~ /^(\w+)(\W.*)$/)
         { $ident = $1;
           $suffix = $2;
         }
       else 
          { $ident = $suffix;
            $suffix = "";
          }
       if ($prefix =~ /\\$/) # For things like \n
          { if ($ident ne "n") {&print_warning("huch:\\ in  quoted code");}
            $prefix .= "L" . $ident; next identloop;
          }
       if ($ident =~ /^[0-9]*$/ )   # just a number
          { $prefix .= $ident; next identloop;}
       if (($usesubscripts eq "yes") && ($ident =~ /^([a-zA-Z])([0-9]+)$/)) 
             { $ident = $1 ."\\underscore\{$2\}"; }
           else { $ident = "\\mathit\{$ident\}"; }
       $prefix .= $ident;
        
      }
   $Ctext = $prefix . $suffix;
   $Ctext =~ s/&/\\&/g;
   $Ctext =~ s/_/\\nspaceunderscore\\_/g; # small negative space before _
   $Ctext =~ s/\./\\nspacedot\./g;  # small negative space before .
   $Ctext =~ s/::/\\DP /g;
   $Ctext =~ s/<</\\ll/g;
   $Ctext =~ s/>>/\\gg/g;
   $Ctext =~ s/ *<= */\\Lle/g;
   $Ctext =~ s/ *>= */\\Lge/g;
   $Ctext =~ s/ *== */\\Leq/g;
   $Ctext =~ s/ *-> */\\Larrow/g;
   $Ctext =~ s/ *\+ */+/g;   # LaTeX takes care of the spacing
   $Ctext =~ s/ *- */-/g;
   $Ctext =~ s/ *\* +/\*/g;
   $Ctext =~ s/ *< */</g;
   $Ctext =~ s/ *> */>/g;
   $Ctext =~ s/ *\+= */\\Lass\{\+\}/g;
   $Ctext =~ s/ *\-= */\\Lass\{\-\}/g;
   $Ctext =~ s/ *\*= */\\Lass\{\*\}/g;
   $Ctext =~ s/ *\/= */\\Lass\{\/\}/g;
   $Ctext =~ s/ *\\&= */\\Lass\{\\&\}/g;
   $Ctext =~ s/ *!= */\\Lass\{\!\}/g;
   $Ctext =~ s/ *\|= */\\Lass\{\|\}/g;



   # All blanks that are still in Ctext are to be preserved and are hence quoted
   $Ctext =~ s/ /\\ /g;
   $Ctext =~ s/\+\+/\\Dplus /g;
   $Ctest =~ s/--/\\Dminus /g;
   # $Ctext =~ s/!=/\\Noteq /g;
   $Ctext =~ s/\\Lle/\\Lle /g;
   $Ctext =~ s/\\Lge/\\Lge /g;
   $Ctext =~ s/\\Leq/\\Leq /g;
   $Ctext =~ s/\\Larrow/\\Larrow /g;
   if ($Ctext =~ /</) 
   { while ($Ctext =~ /^(.*)<([^>]*)>(.*)$/) # template brackets
     { $Ctext =~ s/</\\Lless /g; 
       $Ctext =~ s/>/\\Lgreater /g;
     }
   }
   $Ctext =~ s/%/\\%/g; 
   $Ctext =~ s/\^/\\circumflexop /g;
   $Ctext =~ s/~/\\tildeop /g;
   $Ctext =~ s/'/\\Lrquote /g;
   $Ctext =~ s/`/\\Llquote /g; 
   $Ctext =~ s/\(\)/\(\\;\)/g;      # a little space for empty argument list
   $Ctext =~ s/\,\\ /\,\$\}\n\\mbox\{\$/g;  
       # replace ,blank by ,$}newline\mbox{$ to allow line breaks
   $Ctext = "\\mbox\{\$" . $Ctext . "\$\}";

 $Ctext;
}
  
@ And here are the corresponding \TeX\ commands.

<<special symbols>>=
\def\Lless{\hbox{\tt <}}
\def\Lgreater{\hbox{\tt >}}
\def\<{\hbox{\tt <}}
\def\>{\hbox{\tt >}}
\def\underscore{_}
\def\Lle{\le}
\def\Lge{\ge}
\def\Dplus{{++}}
\def\Dminus{{--}}
\newcommand{\Lass}[1]{\mathrel{{#1}{=}}}
\newcommand{\Lminuseq}{{-}{=}}
\def\Noteq{{!}{=}}
\def\Leq{\equiv}
\def\Larrow{\rightarrow}
\def\tildeop{{\sim}}
\def\Tildeop{{\char126}}
\def\circumflexop{\hbox{\^{}}}
\newcommand{\DP}{\hspace{.1em}{::}\hspace{-.2em}} % symbol for ::
\newcommand{\nspacedot}{\hspace{-0.09em}}
\newcommand{\nspaceunderscore}{\hspace{-0.13em}}
\newcommand{\Lrquote}{\mbox{'}}
\newcommand{\Llquote}{\mbox{`}}
\newcommand{\KLL}{@$\<\<$}
\newcommand{\KGG}{@$\>\>$}
\newcommand{\DLK}{{\tt [[}}
\newcommand{\DRK}{{\tt ]]}}
\newcommand{\Ln}{\mbox{$\backslash${\tt n}}}


@ \subsection{Procedure [[Convert_T]]}

We only need to quote all special characters and to change the font to
typewriter.

<<conversion subroutines>>=

# the following procedure is copied from ext.nw. Please make changes only here.
# I still need  way to maintain consistency with ext.

sub convert_T{
 local($Ctext) = @_; # read argument into local variable
 $Ctext =~ s/&/\\&/g;
 $Ctext =~ s/_/\\_/g;
 $Ctext =~ s/{/\\{/g;
 $Ctext =~ s/}/\\}/g;
 $Ctext =~ s/%/\\%/g; 
 $Ctext =~ s/\^/\\circumflexop /g;
 $Ctext =~ s/~/\\Tildeop /g; 
 return "\{\\tt " . $Ctext . "\}";
}

@ \subsection{Empty lines in code sections and page breaks}

Empty lines in code chunks generate empty vertical space that I find too big. I solve the problem with a postprocessor that works on the file generated by
noweave.

Empty line occur in two forms. In unnamed code sections they appear as \verb-{\tt{}\_\_\_\_}-. Unnamed code chunks start with \verb-\begin{Lcode}-.
In named code chunks they appear as empty lines. Named code chunks start with
nwbegincode.

In a first attempt I simply replaced empty lines by negative vertical space. This has an undesirable side effect. Within code chunks noweb puts LateX in observeline mode. In this mode each line is a paragraph and hence an empty line was converted into a paragraph of negative height. If such a paragraph falls on a line break it is always put on the old page. This causes problems with the textheight. For example footnotes were printed on top of the last line of text.

In my new solution I replace an emptyline by  
\verb-\vspace{some positive value}-, which I make a prefix of the subsequent line. This has the additional effect that the space does not appear at the top of a page. It however corrupts the line count. I correct the line count by adding the appropriate number of lines containing only a \%. Such lines have no effect with respect to LaTeX ans restore the line count. I have also tried to
replace empty lines in code by \verb-\vspace{some positive value}%-; this does not work because \% is not treated as a LaTeX comment in  code sections.

Noweb uses the following rule for page breaking. A code section together with the preceding document chunk are considered a unit. All attempts are made to keep them together. In other words, a unit is placed on a partially complete page only if it fits completely on the page. This rule generates a lot of pages that are only partially full. We need a more flexible rule for the book.

Noweb implements this rule by issuing filbreak commands at appropriate places and by using a very high page breaking penalty within code sections. Filbreak commands are issued at the end of every code section and at the beginning of document chunks that start a new paragraph (i.e., start with @newline). 

It will not do to simply remove the filbreak command. Recall that every line of code is its own paragraph. Thus I will have many pagebreaks within code sections. I want no pagebreaks within the first three and the last three line of
a code section. So I insert nobreak commands at these places. Also I do not discourage page breaks within code as much as noweb and therefore set 
penalty to lowpenalty. This does not work as I expected. 

Note that code is processed in obeylines environment. In this context each newline is an implicite \tc{par}-command. Norman Ramsey redefines this
command as 
\begin{verbatim}
\@@par
\def\par{\leavevmode\null \@@par \penalty\nwcodepenalty}%
\end{verbatim}
i.e., a par-command expands to an old par command followed by a penalty as 
given by nwcodepenalty. I set this value at the end of every code line: to a
very high value for the first three and last three lines and to a low value for
all other lines. The values are given by \tc{Lhighpen}\  and \tc{Llowpen}. After some experiments I settled for values 10000 and -30.

I redefine three commands in noweb.sty. First the standard value of nwcodepenalty is set to 0 instead of highpenalty. This allows line breaks within
code. Secondly I remove the filbreak command form nwendcode and nwdocspar
and set nwdocspar to par. 

<<redefinition of noweb parameters that control pagebreaks>>=
\def\nwendcode{\endtrivlist \endgroup } %\filbreak
\nwcodepenalty=0  %\@highpenalty
\let\nwdocspar=\par%\filbreak 

<<emptyline.pl>>=

$INPUT = $ARGV[0] && shift;

if ($INPUT eq "")
{  print "usage: emptyline expexts an argument\n";
   die;
}

open (INPUT)  || die "Can't find input file $INPUT: $!\n";

while (<INPUT>)
{ $codechunk = ""; 
  if (/nwbegincode/) 
    { $line = $_; chop($line);
      print $line,"\\nwcodepenalty=\\Lhighpen\n"; 
      $_ = <INPUT>;
      $anzahl = 0;           
      while (!/nwendcode/)
        { if (/\S/) {$codechunk .= $_;}
          else {$codechunk .= "\\vspace{\\Lemptyline}"; $anzahl++;}         
          $_ = <INPUT>;
        }
    }
  if (/begin{Lcode}/)
    { print;
      $_ = <INPUT>; 
      $anzahl = 0;          
      while (!/end{Lcode}/)
        { if (/^[\{\}\\ t]*$/) {$codechunk .= "\\vspace{\\Lemptyline}"; $anzahl++;} 
          else {$codechunk .= $_;}         
          $_ = <INPUT>;
        }
    }
  if ($codechunk)
    { $nlines = ($codechunk =~ tr/\n/\n/); $lcount = 0;
      while ($codechunk =~ /^([^\n]*)\n/)
       { $line = $1;  $lcount++;
         $codechunk = $';
         if ($lcount <= 3 || ($lcount >= $nlines - 3 && $lcount < $nlines))  
            {print $line, "\\nwcodepenalty=\\Lhighpen\n";}
         else {print $line , "\\nwcodepenalty=\\Llowpen\n";}
           
       }
      print $codechunk;
    }
    
  print;   # Prints text and nwendcode and end{Lcode} respectively.
  while ($anzahl > 0) {print "\%\n"; $anzahl--;}
}

close(<INPUT>);

<<Lweb.sty>>=
\newlength{\Lemptyline}
\setlength{\Lemptyline}{1ex}
\newcount\Lhighpen \Lhighpen=10000
\newcount\Llowpen \Llowpen=-30




@ \section{Installation Guide}
We assume the existence of environment variables LEDAINCLUDE and LEDAMAN such that LEDAINCLUDE contains the header files of all LEDA data types and LEDAMAN contains the content of the subdirectory man of the LEDA distribution. The latter directory also contains the shell commands Lman, Ldoc, Fman and Mkman. You need to make them accessible as commands (either by adding LEDAMAN to your PATH or by copying them to a directory already listed in PATH). 

Put LEDAMAN into TEXPATH.

In SB we have

LEDAINCLUDE=/LEDA/SRC/incl/LEDA
LEDAMAN=/KM/usr/mehlhorn/LEDA/Manual/Noweb

\section{Changes}
I record the changes made after the end of the trial phase.
\begin{itemize}
\item July 10, 96: xdvi=no and latexruns >= 1 implies that the produced dvi-file
is copied into T.dvi in the working directory. This required to add one statement.
\verb+cp /tmp/... $owd/$basename.dvi+.
\item July 10, 96: 
\begin{verbatim}
wir (Stefan und Christian) mussten um dynamic link libraries unter Windows
    zu erzeugen 3 Macros in die Header einfuegen:
    __exportC, __exportF, __exportD  sie koennen bei Klassen, Funktionen und
    Variablen wie folgt auftauchen: 

    class __exportC  A { ... };

    type  __exportF  func()

    type  __exportD  var;

     In der Unix-Version wollen wir die Macros vor Auslieferung herausfiltern,
     aber in unserer Arbeitsversion stehen sie drin, und insbesondere mit
     dem __exportF kommt Lman natuerlich nicht zurecht.
\end{verbatim}
I use the following solution. Whenever a code unit has been built I remove all words in the list [[invisible_words]] from the code unit. This is done in section [[determine code unit]]. The list is also defined there.
\item July 11, 96: discovered that Fman handles the filter opname incorrectly.
Corrected it.
\item Every call of Lman starts from scratch. extracts the manual, calls latex, and finally xdvi. I introduce a directory /MANUAL/DVI where I store all
dvi-files. The utility Mkdvi makes all dvi-files. Lman (with option xdvi=yes)
first looks up whether the dvi-file exists and if so displays it.
\end{itemize}
\end{document}
