% This file should be typeset by
%
%	lw2nw ext.nw > ext1.nw;
%	noweave -delay ext1.nw > ext.tex
%	latex ext.tex (2x)

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

\input MANUAL.pagesize
\input MANUAL.mac

\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
	Michael Seel \and Christian Uhrig}
\maketitle
\tableofcontents
\newpage

\section{The Manual Page of the Documentation Tools}

\subsection{How to use the manual production tools}
LEDA offers several tools for manual production and documentation.
The following diagram shows the different extraction and conversion
processes possible from a documented and manual commented file 
to the different intermediate files for further processing.

\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 ______   C/C++ 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            Manual               DVI
   |          _____|_______________
 LEDA        |     |        |      |
            cmd   noweb    tex   MANUAL
\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 Manual contains all the relevant commands and tex files.

\begin{description}
\item[Lman] 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
\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:

[[size={12,11,10}]]\\
[[constref={no,yes}]]\\
[[partypes={no,yes}]]\\
[[usesubscripts={no,yes}]]\\
[[numbered={no,yes}]]\\
[[xdvi={yes,no}]]\\
[[warnings={yes,no}]]\\
[[informational={yes,no}]]\\
[[ack={yes,no}]]\\
[[latexruns={1,2,0}]]\\
[[filter={all, signatures, definition, types, 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).

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

\item[Mkman] is the tool to produce manuals like the LEDA manual. 

\item[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.
 
\item[lweave] is the weave tool for Lweb.
\end{description}

The production of manual pages and full documentations proceeds in phases.
\begin{description}
\item[Lman]
\begin{verbatim}
XXX.[h|lw|nw|w]  ----->  XXX.tex   -------> XXX.dvi
                 ext.pl             latex
\end{verbatim}
\item[lweave and lw2dvi]
\begin{verbatim}
XXX.lw ---------->  XXX.tex -------> XXX.dvi
         lweave              latex
\end{verbatim}

\item[Ldoc]
\begin{verbatim}
XXX.[lw|nw|w] ----> temp.[lw|nw|w] --------------> XXX.tex -------> XXX.dvi
  |           ext.pl               [l|no|c]weave       |   latex
  | ext.pl                                             |
  |                                                    |
XXX.man -----------------------------------------------
                   \input
\end{verbatim}
\item[Fman]
\begin{verbatim}
XXX.[h|lw|nw|w]  ----------> ASCII
                    Fman
\end{verbatim}
\end{description}

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. 


\subsection{How to create a Manpage}
Starting from a C++ data type [[DT]] we give the documentation
process and its syntactical elements in form of a context
free grammar. Non-terminals are marked by \verb-<...>-. Terminals
are pseudocode statements like [[text_text_text]] which represent
pieces of latex text apart from the C++ language constructs which
should be easy to locate. Optional syntactical elements are put
in square brackets \verb-[...]-.

\begin{verbatim}
<Augmented C++-File> -> <Manpage Statement>
			class DT {
			<Mdefinition Statement>
			<Mtypes Statement>
			<Mcreation Statement>
			<Moperations Statement>
			};
			<Moperations Statement>
			<Mimplementation Statement>
			<Mexample Statement>
\end{verbatim}
The previous picture should give you an impression about the
possible sectioning of the implementation of [[DT]]. Note that
several of the cited sections are optional and are not necessarily
part of the data types manpage specification. We now handle the
different sections.


\subsubsection*{The Manpage Statement}
\begin{verbatim}
<Manpage Statement> -> 
	/*{\Manpage {DT} {T1,..,Tk} {short_description} {d}}*/
\end{verbatim}
This comment is mandatory for the start of a manpage. It introduces
the data type to the macro package and sets the main variable 
\verb-\Mname = DT<T1,..,Tk>-. Thus [[DT]] the data types name. 
[[T1,..,Tk]] is a list of template parameters which can be empty.
the [[short_description]] appears in the manpage header and can be used
as a latex reference. Finally \verb-\Mvar- is set to [[d]] as the
default variable name of a class instance.


\subsubsection*{The Mdefinition Statement}
\begin{verbatim}
<Mdefinition Statement> -> 
	/*{\Mdefinition specification_text}*/
\end{verbatim}
This comment is somehow mandatory as a manpage should always contain
an accurate specification of a data type.

\subsubsection*{The Mtypes Statement}
\begin{verbatim}
<Mtypes Statement> -> 
	/*{\Mtypes [W]}*/
	<list of local type definitions>
\end{verbatim}

This comment is optional. It should be placed in a public section of class
[[DT]] where the user wants to specify local types in class scope. [[W]] is an
optional width specifier in cm determining the width of the indendation of the
following type specifications.

\begin{verbatim}
<list of local type definitions> ->
	typedef  TYPE1	LOCALTYPE1;
        /*{\Mtypedef typedef_documentation}*/
	<list of local type definitions>
\end{verbatim}
This triggers a documenation line containing the whole typedef statement
followed by [[typedef_documentation]].

\begin{verbatim}
<list of local type definitions> ->
	typedef TYPE2	LOCALTYPE2;
        /*{\Mtypemember type_documentation}*/
	<list of local type definitions>
\end{verbatim}
This triggers a documenation line containing only the defined type
[[LOCALTYPE2]] followed by [[type_documentation]].

\begin{verbatim}
<list of local type definitions> ->
	class LOCALTYPE3 {
        /*{\Mtypemember type_documentation}*/
 	  // local class implemenation
	};
	<list of local type definitions>
\end{verbatim}
This triggers a documenation line containing only the defined type
[[LOCALTYPE3]] followed by [[type_documentation]].

\begin{verbatim}
<list of local type definitions> ->
	enum LOCALTYPE4 { T1, ... , Tk };
        /*{\Menum type_documentation}*/
	<list of local type definitions>
\end{verbatim}
This triggers a documenation line containing the defined enum type
[[LOCALTYPE4]] followed by [[type_documentation]].

\begin{verbatim}
<list of local type definitions> -> <empty>
\end{verbatim}


\subsubsection*{The Mcreation Statement}
\begin{verbatim}
<Mcreation Statement> ->
	/*{\Mcreation [MVAR] [W]}*/
	<list of constructors>
\end{verbatim}
This comment is somehow mandatory as most classes have constructors which have
to be documented. [[MVAR]] can be used to set \verb-\Mvar- to the string
[[MVAR]]. [[W]] is an optional width specifier in cm determining the width of
the indendation of the following construction operations.

\begin{verbatim}
<list of constructors> ->
	DT(paramlist);
	 /*{\Mcreate constructor_specification }*/
	<list of constructors>
\end{verbatim}
creates the documenation for the constructor [[DT(paramlist)]].

\begin{verbatim}
<list of constructors> ->
	~DT();
	 /*{\Mdesctruct desctructor_specification }*/
	<list of constructors>
\end{verbatim}
creates the documenation for the destructor [[~DT()]].

\begin{verbatim}
<list of constructors> -> <empty>
\end{verbatim}

\subsubsection*{The Moperations Statement}
\begin{verbatim}
<Moperations Statement> ->
	/*{\Moperations [W1] [W2]}*/
	<list of operation definitions>
\end{verbatim}
This comments starts the operations section of the manpage which usually is
dominating the manpage. [[W1]] is an optional width specifier determining the
indendation used for the return type of all following operations.  [[W2]] is an
optional width specifier determining the width of the additional indendation
up to the textual specification block. In the following we give all possible
kinds of manual comments documenting member operations and friend operations
of a class.
\begin{verbatim}
<list of operation definitions> ->
	<operation definition> <list of operation defintions> |
	<empty>
\end{verbatim}
The following entries should be rather self explaining. The first section
provides documentation elements concerning member operations. Top down
we have standard named member operations, static operations, conversion
operations, binary operators, unary operatos and the special selection
operator known from arrays. 
\begin{verbatim}
<operation definition> ->
	return_type operation_name(paramlist);
	/*{\Mop semantic_description }*/ 		|
	return_type static_operation_name(paramlist);
	/*{\Mstatic semantic_description }*/ 		|
	return_type conversion_operation_name(paramlist);
	/*{\Mconversion semantic_description }*/ 	|
	return_type operator binary_op_symbol (paramlist);
	/*{\Mbinop semantic_description }*/ 		|
	return_type operator unary_op_symbol (paramlist);
	/*{\Munop semantic_description }*/ 		|
	return_type operator [] (paramlist);
	/*{\Marrop semantic_description }*/ 	
\end{verbatim}
The next section gives documentation elements suitable for
friends in classes or for global functions.
\begin{verbatim}
<operation definition> ->
	return_type friend_operation_name(paramlist);
	/*{\Mfunc semantic_description }*/ 		|
	return_type friend_operator binary_op_symbol (paramlist);
	/*{\Mbinopfunc semantic_description }*/ 	|
	return_type friend_operator unary_op_symbol (paramlist);
	/*{\Munopfunc semantic_description }*/ 	
\end{verbatim}
Finally there's a function object documentation element.
\begin{verbatim}
<operation definition> ->
	constructor(paramlist);
	/*{\Mfunobj{return_type} semantic_description }*/
\end{verbatim}


\subsubsection*{The Mimplementation Statement}
\begin{verbatim}
<Mimplementation Statement> ->
	/*{\Mimplementation implemenation_information }*/
\end{verbatim}
This section can be used to give the user certain implemenation details
like running time, space requirements or implementation specific
informations which are helpfull for the user of the data type.


\subsubsection*{The Mexample Statement}
\begin{verbatim}
<Mexample Statement> ->
	/*{\Mexample (example_description [<verbatim_example_block>])* }*/
\end{verbatim}
In this section you should provide a small example demonstrating the usage of
[[DT]]. [[example_description]] is just regular latex description.

\begin{verbatim}
<verbatim_example_block> ->
	\begin{Mverb} 
	verbatim_multi_line_example_code
	\end{Mverb}
\end{verbatim}
This is just an optional block structure enabling code citation within the
manual comment.


@ \subsection{A Manpage Example}
This section gives a short example of a manpage following the above
specifications.

\begin{figure}
{\footnotesize
\begin{verbatim}
#ifndef LEDA_STACK_H
#define LEDA_STACK_H

#include <LEDA/basic.h>
#include <LEDA/impl/slist.h>

/*{\Manpage {stack} {E} {Stacks} {S}}*/

template<class E> class _CLASSTYPE stack : private SLIST
{
/*{\Mdefinition
An instance |S| of the parameterized data type |\Mname| 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.}*/

public:

/*{\Mcreation}*/

  stack() {}
/*{\Mcreate creates an instance |\Mvar| of type |\Mname| and initializes 
it to the empty stack.}*/

  stack(const stack<E>& S) : SLIST(S) {}
 ~stack() { clear(); }
  stack<E>& operator=(const stack<E>& S) 
  { return (stack<E>&)SLIST::operator=(S); }

/*{\Moperations 2.5 4}*/

E top()   const { return ACCESS(E,SLIST::head());}
/*{\Mop      returns the top element of |\Mvar|.\\ 
             \precond $S$ is not empty.}*/

void push(E x)  { SLIST::push(Copy(x)); }
/*{\Mop      adds $x$ as new top element to |\Mvar|.}*/

E pop()         { E x=top(); SLIST::pop(); return x; }
/*{\Mop      deletes and returns the top element of |\Mvar|.\\ 
             \precond $S$ is not empty.}*/

\*{\Mimplementation
Stacks are implemented by singly linked linear lists. All operations take 
time $O(1)$.}*/ 

#endif
\end{verbatim}
}% end footnotesize
\caption{The header file stack.h}
\label{the header of stack}
\end{figure}

\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 produced from stack.h}
\label{intermediate tex-file}
\end{figure}

Figure \ref{intermediate tex-file} shows the intermediate \TeX-file produced by
Lman for the data type stack.  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.


\newpage
\section{Implementation of Toplevel Callers}
\subsection{The ASCII View}
<<Fman>>=
#!/bin/sh -f
perl $LEDAROOT/Manual/cmd/ext.pl Fman $1 $2

@ \subsection{The \LaTeX\ View}
<<Lman>>=
#!/bin/sh -f
perl $LEDAROOT/Manual/cmd/ext.pl Lman "$@"

<<Ldoc>>=
#!/bin/sh -f
perl $LEDAROOT/Manual/cmd/ext.pl Ldoc "$@"

<<lextract>>=
#!/bin/sh -f
if [ "$1" = "" -o "$2" = "" ] 
then
  echo ""
  echo "Usage is"
  echo "          lextract infile outfile [options]"
  echo ""
  echo "Extracts the manual comments from infile into outfile."
  exit
fi
infile=$1
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 $f
   lextract $f  extract/`basename $f .$ext`.tex > Mkman.log
end


<<Mkdvi>>=
#!/bin/sh

#lroot=$LEDAROOT

lroot=../..

# check for perl and latex

echo " "

path=`which perl`

if [ -x "$path" ]; then
   echo using $path
else
   echo Cannot execute perl.
   echo " "
   exit 0
fi

path=`which noweave`

if [ -x "$path" ]; then
   echo using $path
else
   echo Cannot execute noweave.
   echo " "
   exit 0
fi

path=`which latex`

if [ -x "$path" ]; then
   echo using $path
else
   echo Cannot execute latex.
   echo " "
   exit 0
fi


source=$lroot/incl/LEDA
dvidir=$lroot/Manual/DVI

cd $dvidir

cp $lroot/Manual/MANUAL/intro.tex ./Introduction.tex
cp $lroot/Manual/MANUAL/Preface.tex .
cp $lroot/Manual/MANUAL/Basics.tex .

latex Introduction > /dev/null

echo " "
echo Updating xlman dvi-files in `pwd`  ...
echo " "

if [ -x /usr/local/bin/grep ]; then
  grep_cmd=/usr/local/bin/grep
elif [ -x /usr/bin/grep ]; then
  grep_cmd=/usr/bin/grep
else
  grep_cmd=grep
fi

tcmd=`which test`

if [ "$tcmd" = "" ]; then
  tcmd=test
fi

for f in $source/*.h; do
  if $grep_cmd -q Manpage $f; then
     dvi=`basename $f .h`.dvi

     if $tcmd ! $dvi -nt $f; then
        echo $dvi
        perl ../cmd/ext.pl Lman $f xdvi=no dvioutfile=$dvi >> mkdvi.log
     fi
  fi
done

rm -f *.log

cd ..


<<Mkdvisfrom>>=
#!/bin/sh

# check for perl and latex

echo " "

if perl $LEDAROOT/Manual/cmd/ext.pl; then
   echo "perl  ok"
else
   echo Cannot execute perl.
   echo " "
   exit 1
fi

if noweave < /dev/null > /dev/null; then
   echo "noweb ok"
else
   echo Cannot execute noweave.
   echo " "
   exit 1
fi

echo '\\documentclass{article}' > dummy.tex
echo '\\begin{document} hw \\end{document}' >> dummy.tex
echo '' >> dummy.tex
if latex dummy.tex > /dev/null; then
   echo "latex ok"
   rm -rf dummy.*
else
   echo Cannot execute latex.
   echo " "
   exit 1
fi


source=$1

echo " "
echo Constructing dvi-files for xlman in `pwd`  ...
echo " "

if [ -x /usr/local/bin/grep ]; then
  grep_cmd=/usr/local/bin/grep
elif [ -x /usr/bin/grep ]; then
  grep_cmd=/usr/bin/grep
else
  grep_cmd=grep
fi

for f in $source/*.h; do
  if $grep_cmd -q Manpage $f; then
    ln -s $f .
  fi
done

for f in *.h; do
  fbase=`basename $f .h`
  fbase=`basename $fbase _decl`
  perl $LEDAROOT/Manual/cmd/ext.pl Lman $f xdvi=no dvioutfile=$fbase.dvi 
done

rm -f *.h *.log

@ \subsection{The HTML View}
The command [[Mkhtml]] makes the html-version of the LEDA-manual.  It can be
called in any directory. It gets the necessary tex and header files via
[[LEDAROOT]]. The tasks are done by the subprocesses [[Mktoplevel]] and
[[Mklowlevel]] described below.

Having set up the necessary tex-files we call [[latex MANUAL]] twice and then
[[latex2html]] once.  This will construct the html-version of the manual in the
subdirectory [[MANUAL]]. 

<<Mkhtml>>=
#!/bin/csh -f
set verbose on

\rm -r -f extract
mkdir extract

echo "Preparing all tex-files for LEDA types"
echo " "

Mklowlevel

echo  "Preparing top level of the Manual"
echo " "

Mktoplevel

echo "calling latex MANUAL.tex"
echo " "

latex MANUAL.tex
latex MANUAL.tex
dvips MANUAL

echo "please ensure that your path does not contain dots!!!"
echo "calling latex2html MANUAL.tex"
echo ""

\rm -rf MANUAL

latex2html $* -split 4 -local_icons -up_url 'http://www.mpi-sb.mpg.de/LEDA' -up_title 'LEDA home page'  MANUAL.tex


@ Mktoplevel prepares the top level of the manual. 
\begin{itemize}
\item It copies all tex-files and subdirectory prog from the parent directory.
\item It applies [[rm_dangerous_macros]] to all these files. latex2html insists
that the command names of LaTeX commands consist of letters only. We used
\verb-\<-, \verb-\>-, and \verb-\g++-. We remove them.
\item We want the crossreferences to appear nicely in the
html-document. latex2html replaces all \verb-\ref- by hyperlinks but an
ordinary ref or pageref appears only as a box. Named links are
nicer. [[handle_refs]] replaces occurrences of \verb-\ref{label}- by
\verb-\htmlref{label'}{label}- where label' is obtained by quoting underscores.
\end{itemize}
<<Mktoplevel>>=
#!/bin/csh -f

foreach f ($LEDAROOT/Manual/MANUAL/*.tex)
   set core = `basename $f .tex`
   echo "preparing $core for the html-manual"
   cp $f TEMP1
   perl $LEDAROOT/Manual/cmd/rm_dangerous_macros.pl TEMP1 > TEMP2
   perl $LEDAROOT/Manual/cmd/handle_refs.pl TEMP2 > $core.tex
end

\rm -r -f prog
mkdir prog

foreach f ($LEDAROOT/Manual/MANUAL/prog/*.prog)
   set core = `basename $f`
   echo "preparing $core for the html-manual"
   cp $f TEMP1
   perl $LEDAROOT/Manual/cmd/rm_dangerous_macros.pl TEMP1 > TEMP2
   perl $LEDAROOT/Manual/cmd/handle_refs.pl TEMP2 > prog/$core
end

\rm -f TEMP1
\rm -f TEMP2


@ latex2html gets confused by macros \verb-\<-, \verb-\>>-, and \verb-\g++-. I
change them to Ltemplateless, Ltemplategreater, and gpp. I(MS) conjecture that
the new version can handle them. :-)

<<rm_dangerous_macros>>=
#!/bin/sh -f
mv $1.tex $1.temp
perl $LEDAROOT/Manual/cmd/rm_dangerous_macros.pl $1.temp > $1.tex

<<rm_dangerous_macros.pl>>= 

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

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

while (<INPUT>)
{ s/\\</\\Ltemplateless /g;
  s/\\>/\\Ltemplategreater /g;
  s/\\g\+\+/\\gpp /g;
  s/\\'/^\\prime /g;                       
  print ;
}

  
@ I am handling refs and pagerefs.
<<handle_refs>>=
#!/bin/csh -f

foreach f (*.tex)
   echo "handling refs for $f"
   set core = `basename $f .tex`
   mv $core.tex $core.temp
   perl $LEDAROOT/Manual/cmd/handle_refs.pl $core.temp > $core.tex

end

perl $LEDAROOT/Manual/cmd/handle_refs.pl $1.temp > $1.tex

<<handle_refs.pl>>= 

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

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

while (<INPUT>)
{ if (/\\ref\{([^\}]*)\}/)
  { $key = $1; $key1 = $key; $key1 =~ s/_/\\_/;
    s/\\ref\{$key\}/\\htmlref\{$key1\}\{$key\}/g;
  }
  if (/\\pageref\{([^\}]*)\}/)
  { $key = $1; $key1 = $key; $key1 =~ s/_/\\_/;
    s/\\pageref\{$key\}/\\htmlref\{$key1\}\{$key\}/g;
  }
  print;
}

@ Making the lower level is simple. We only need to call Lman in mode
HTMLh2html to extract the appropriate Tex-file. We send the texfile through
[[rm_dangerous_macros]] to be on the safe side.

<<Mklowlevel>>=
#!/bin/csh -f

set source = $LEDAROOT/incl/LEDA
set ext = h

cd extract

foreach f ($source/*.$ext)
   echo "preparing tex-file (html) for $f"
   set core = `basename $f .$ext`
   perl $LEDAROOT/Manual/cmd/ext.pl Lman $f mode=HTMLh2html outfile=TEMP1 informational=no
   perl $LEDAROOT/Manual/cmd/rm_dangerous_macros.pl TEMP1 > $core.tex
end

cd ..


@ The command [[HTMLman T]] makes the html version of the manual page for type
T. The command looks for files [[T.lw]], [[T.nw]], [[T.w]], [[T.h]] in this
order and produces a tex-file [[T.tex]]. The tex-file is sent through 
latex twice and then through latex2html. The entry node to the html manual page
is [[T/T.html]].

<<HTMLman>>=
#!/bin/csh -f
echo "extracting file $1.tex"
echo " "

perl $LEDAROOT/Manual/cmd/ext.pl Lman $1 mode=HTMLman outfile=TEMP1
perl $LEDAROOT/Manual/cmd/rm_dangerous_macros.pl TEMP1 > $1.tex 
\rm -f TEMP1

latex $1.tex
latex $1.tex

latex2html -font_size 12pt -split 0 -antialias -local_icons $1.tex
  # we require version > 98.1
echo "netscape -raise -remote openFile($1/$1.html)";
set here = `pwd`;
netscape -raise -remote "openURL($here/$1/$1.html)"
  # we use netscape version > 4.0

<<Mkhtmlshort>>=
#!/bin/csh -f
set verbose on

echo "calling latex MANUAL.tex"
echo " "

latex MANUAL.tex
latex MANUAL.tex

\rm -r -f MANUAL

latex2html -split 4 -local_icons -up_url 'http://www.mpi-sb.mpg.de/LEDA' -up_title 'LEDA home page' -no_reuse MANUAL.tex


@ \section{The Main Engine: ext}

\subsection{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>>

@ \subsection{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;
$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";
$informational = "yes";
$debugging = "no";
  # default is to give warnings, to give progress report 
  # and to show the result
$filter = "all";        
  # usually we show everything

$pid = "";            
  # we do not know the process id yet
$latexruns=1;
@substlist = ();     
  # a list L1,R1,L2,R2,....  of all substitutions
$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.
$noweaveoptions = "";  
  # we start with no options.
if ($mode eq "Lman" || $mode eq "Mkman" || 
    $mode =~ /HTML/ || $mode eq "Fman" )
{ $print_title = "yes"; }
else
{ $print_title = "no"; }

$HTMLopentabular = "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","types",  
                         "creation","operations","implementation","example") {
      if ($filter eq $candidate) { goto filterfound; }
    }
    &print_info("Searching for operation $filter of type $filearg");
    filterfound:
  } 
}
else {
  foreach $path ("HOME","PWD") {
    if ($path eq "HOME") {
      $CFG = $ENV{$path} . "\/" . $mode . "\.cfg";
    }
    else {
      $CFG = $mode . "\.cfg";
    }
    if (-e $CFG) {
      open (CFG); 
      &print_info("Reading $CFG");
      while (<CFG>) {
        if (/^(\w+)=(.*)$/) 
	{ eval "\$$1 = \$2"; } 
      }
      close (CFG);
    }
  }
  eval "\$$1 = \$2" while $ARGV[0] =~ /(\w+)=(.*)/ && shift; 
}

if ($informational eq "no") { $dontshowinfo = '> /dev/null'; }
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\\ \verb-$LEDAROOT- to
the LEDA root directory \verb-$INCL- to the directory containing all LEDA
header files,\\ \verb-$basename- to the file argument minus the extension (if
any),\\ \verb-$INPUT- to the input file ( either [[\$basename.[lw|w|nw|h] ]]
in the working directory or \verb-$basename.h- in the LEDAINCLUDE directory,\\
\verb-$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.

In HTML mode we need to read three files: 
\begin{verbatim}
  $LEDAROOT/Manual/noweb/texreplacementtable,
  $LEDAROOT/Manual/noweb/namereplacementable, and 
  $LEDAROOT/Manual/noweb/refreplacementable
\end{verbatim}

The first file contains lines of the form\\ \verb-cmd xxx-\\ where \verb-\cmd-
is a tex-command and [[xxx]] is any string not containing a backslash. Any
occurence of \verb-\cmd- is replaced by [[xxx]] in the detex-phase of
translation to HTML. If [[xxx]] is missing it is assumed to be [[cmd]].

The second file contains lines of the form\\
\verb-xxx  yyy-\\
where [[xxx]] is any name which we want to tag in the LEDA manual 
and [[yyy.html]] is the html-file to which we want to make the link.
If [[yyy]] is missing then it is assumed to be [[xxx]].

The third file contains lines of the form\\
\verb-xxx yyy-\\
where [[xxx]] is any label which we set in our manual and [[yyy.html]]
is the html-file to which we want to make the link.

<<set up input and output files>>=

&print_info("$mode version 2.2b");
if (!($filearg)) { 
  &print_usage($mode); 
}
if ( $filearg eq "mancommands" ) {
  &print_mancommands($mode);
}
if ( $filearg eq "ltools" || 
     $filearg eq "Lman" ||
     $filearg eq "Ldoc") {
  &print_ltools($mode);
}


$LEDAROOT = $ENV{"LEDAROOT"};
$INCL = $ENV{"LEDAROOT"} . "/incl/LEDA";

if ($mode =~ /HTML/) {
  $INPUT = "$LEDAROOT/Manual/noweb/texreplacementtable";
  open (INPUT)  || die "Error: Can't find input file $INPUT: $!\n";
 
  while (<INPUT>) {
    chop;
    if (/^\s*$/) { next; } # skip empty lines
    s/\t/ /g;  # subsitute a tab by a blank; some people write xxx\tyyy
    if (/^\s*(\S+)\s+(\S.*)$/) {
      $texcommand = $1;
      $replacement= $2;
    }
    else {
      /^\s*(\S+)\s*$/;
      $texcommand = $1;
      $replacement = $1;
    }
    $texreplacementtable{"$texcommand"} = $replacement;
  }
  close (INPUT);
       
  $INPUT = "$LEDAROOT/Manual/noweb/namereplacementtable";
  open (INPUT)  || die "Error: Can't find input file $INPUT: $!\n";
 
  while (<INPUT>) {
    chop;
    if (/^\s*$/) { next; } # skip empty lines
    s/\t/ /g;  # subsitute a tab by a blank; some people write xxx\tyyy
    if (/^\s*(\S+)\s+(\S+)\s*$/) {
      $LEDAname = $1;
      $URL = $2;
    }
    else {
      /^\s*(\S+)\s*$/;
      $LEDAname = $1;
      $URL = $1;
    }
    $namereplacementtable{"$LEDAname"} = $URL;
  }
  close (INPUT);

  $unrecognizedtex = "unrecognizedtex.log";
  open(UNRECOGNIZEDTEX,">>$unrecognizedtex");

  $INPUT = "$LEDAROOT/Manual/noweb/refreplacementtable";
  open (INPUT)  || die "Error: Can't find input file $INPUT: $!\n";
 
  while (<INPUT>) {
    chop;
    if (/^\s*$/) { next; } # skip empty lines
    s/\t/ /g;  # subsitute a tab by a blank; some people write xxx\tyyy
    if (/^\s*([ \w]*\w)\s*\&\s*(\w+)\s*$/) {
      $LEDAname = $1;
      $URL = $2;
    }
    else {
      /^\s*(\S+)\s*$/;
      $LEDAname = $1;
      $URL = $1;
    }
    $refreplacementtable{"$LEDAname"} = $URL;
  }
  close (INPUT);

  $unrecognizedref = "unrecognizedref.log";
  open(UNRECOGNIZEDREF,">>$unrecognizedref");
}

if ($filearg =~ /(.*)\.[whln]/)
{ $basename = $1; }
else
{ $basename = $filearg; }

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"; }

if ($mode eq "Lman" && $xdvi eq "yes" && 
    (-e "$LEDAROOT/Manual/DVI/$basename.dvi")) {
  &print_info("  Taking $LEDAROOT/Manual/DVI/$basename.dvi as a shortcut");
  system("xdvi $LEDAROOT/Manual/DVI/$basename.dvi $dontshowinfo");
  exit;
}    

DONE:
open (INPUT)  || die "Error: Cannot find input file $basename.[w|lw|nw|h]: $!\n\n";

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


@ 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 "HTMLman" )
{ print OUTPUT "\\documentclass[a4paper]{article}\n";
  print OUTPUT "\\usepackage{html}\n";
  print OUTPUT "\\input MANUAL.mac\n";
  print OUTPUT "\\begin{document}\n";
}
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"; }


@ \subsection{The Main Loop}

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


@ \subsubsection{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', 
	            '__typename');
foreach $invis_word (@invisible_words) {
  $code_unit =~ s/$invis_word//g;
}
$original_code_unit = $code_unit;


@ \subsubsection{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"); 
}

$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

if (! ($command eq options)) {
  &apply_Msubst(*Mcomment); 
}
# we replace all substitution strings in the comment as an exception
# you can escape any string by a preceding backslash.



@ \subsubsection{Processing a Manual Command}

At this point we have completely read a manual comment. We have the command
(without the leading M) available in \verb-$command- and we have the remainder
of the comment available in \verb-$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 'types' ||
      $command eq 'creation' ||
      $command eq 'operations' ||
      $command eq 'implementation' || 
      $command eq 'example') {
    <<definition etc.>> 
    last switch;
  }
  if ($command eq 'text'  || $command eq "preamble") {
    <<text or preamble>> 
    last switch;
  }
  if ($command eq 'enum') {
    <<enum>> 
    last switch;
  }
  if ($command eq 'typedef') {
    <<typedef>> 
    last switch;
  }
  if ($command eq 'typemember') {
    <<typemember>> 
    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.


@ \subsection{The Toplevel Manual Commands}
\subsubsection{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.  The filter
variable in used in regular expressions and it is therefore necessary to quote
all special characters.

<<options>>= 
$Mcomment =~ s/\s//g;
$Mcomment =~ /^(\w+)=(.*)$/ ;


if ($1 eq outfile) {
  if ($print_title eq "no") { 
  # gives information if we are in Lman/Mkman mode 
  # where we don't want to change the outfile but 
  # just parse the manual comments in one file in
  # the given sequence
    close(OUTPUT);
    $outfile = $2;
    if ( $exisiting_outfiles{$output} == 1 )
    { open OUTPUT, ">>$outfile"; }
    else
    { $existing_outfiles{$output} = 1;
      open OUTPUT, ">$outfile";  
    }
  }
}
else
{  eval "\$$1 = \$2"; }

if ($nextwarning eq "no") {$justset = "yes";}


@ \subsubsection{Msubst}
The comment is a sequence of lines each containing either a pair w1 w2 or a
pair w1 \# w2.. We put them into [[\$map]]. Note that the first line may be
empty and contains only a carriage return or line feed.
We do the following substitution strategy. We substitute the w1 by w2 in
all [[code_unit]] and [[Mcomment]] just after they have been detected.
If you want to keep a generally replaced string (as defined by Msubst)
you can escape it with a backslash $\\$. This keeps the string and the
backslash will be erased before prettyprinting.

<<subst>>= 
while ($Mcomment =~ s/^([^\n\r]*)[\r\n]//) 
{ $substline = $1;
  if ($substline =~ /^(.*)#(.*)$/ || $substline =~ /^ *(\S+) +(\S+) *$/)
  { $leftside = $1; $rightside = $2;
    &remove_enclosing_blanks($leftside);
    &remove_enclosing_blanks($rightside);
    push(@substlist,$leftside); push(@substlist,$rightside);
  }
  else
  { if ($substline =~ /\S/) 
      { &print_warning("Msubst does not understand $substline"); }
  }
}
 
@ \subsubsection{Manpage}

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 ($print_title eq "yes") {
  # 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
  if ($mode ne "Fman") {
    $Mtype1 = $Mtype;
    $Mtype1 =~ s/_/\\_/g;
    if ($numbered eq "yes" ) {$star = "";} else {$star = "*";}
    if ($mode =~ /HTML/) {
      &closetabular();
      $star = "";
    }
    print OUTPUT "\\$section" , $star, "{",$title," (",$Mtype1,
                 ")}\\label{",$title,"}\n\\label{$Mtype}\n\n";
  } else {
    print "$title ( $Mtype )\n\n";
  }
}

 
@ \subsubsection{Mdefinition, Mcreation, Mtypes, Moperations, Mexample and 
Mimplementation}

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:

\begin{enumerate}
\item Mcreation: determine varname and declwidth. Set [[\$Mcomment]] to empty
string. Moperations: determine typewidth and callwidth. Set [[\$Mcomment]] to
empty string. All others: Do nothing
\item Store [[\$Mcommand]] in [[\$currentsection]]
\item 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.
\end{enumerate}

<<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_warning("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 "types") {
  # Mcomment may contain a length.
  @params = split(' ',$Mcomment);  # split at blanks
  foreach $i (0 .. $#params) {
    $a = $params[$i];
    if ($a =~ /^ *$/) 
    { &print_warning("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 =~ /HTML/) {
    $semantics = &substitute_for_placeholders($Mcomment);
    $semantics = &convert_HTML($semantics);
    if ( $semantics ne "" ) { $semantics .= "\n"; }
    if ($command eq "definition") {
      print OUTPUT "\\textbf{\\large Definition}\n\n" , $semantics;
    }
    elsif ($command eq "creation") {
      &closetabular();
      print OUTPUT "\\textbf{\\large Creation}\n\n", $semantics;
    }
    elsif ($command eq "types") {
      &closetabular();
      print OUTPUT "\\textbf{\\large Types}\n\n", $semantics;
    }
    elsif ($command eq "operations") {
      &closetabular();
      print OUTPUT "\\textbf{\\large Operations}\n\n" , $semantics;
    }
    elsif ($command eq "implementation") {
      &closetabular();
      print OUTPUT "\\textbf{\\large Implementation}\n\n" , $semantics;
    }
    elsif ($command eq "example") {
      &closetabular();
      print OUTPUT "\\textbf{\\large Example}\n\n" , $semantics;
    }
  }
  elsif ($mode eq "Fman") {
    print $command , "\n____________________________\n\n" , 
    &substitute_for_placeholders($Mcomment), "\n\n"; 
  }
  else { # Lman, Ldoc here !
    $output = "\\" . $command ;
    if ($Mcomment) { $output .= "\n" . &convert_text($Mcomment);}
     &print_unit($output);
  }
}
      
@ \subsubsection{Mtext and Mpreamble}

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

In HTML mode we also have to be careful if the text appears in the
creation section or operations sections.

<<text or preamble>>=
      
if ($filter eq "all" || $filter eq $currentsection ) { 
  if ($mode eq "Fman" || $mode =~ /HTML/) {
    if ($mode eq "Fman") {
      print &substitute_for_placeholders($Mcomment) , "\n\n";
    }
    else {
      &closetabular();
      &print_unit(&convert_HTML(&substitute_for_placeholders($Mcomment)));
    }
  }
  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
   if ( $text ne "" ) { $text .="\n\n"; }
   print OUTPUT $text;
}

@ \subsection{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
}  

@ \subsubsection{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;
  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;
}

sub apply_Msubst{
  local(*alias) = @_;
  local($i) = 0;
  while ($i < @substlist)
  { $leftside =  @substlist[$i]; $i++;
    $rightside = @substlist[$i]; $i++;
    $alias =~ s/^$leftside/$rightside/g;
    $alias =~ s/([^\\])$leftside/$1$rightside/g;
    # \name can be used as an escape symbol to keep name
    $alias =~ s/\\$leftside/$leftside/g;
    # when escaping \name we delete the \ for typesetting
  }
}

@ \subsubsection{Web to latex}  

[[web_to_latex]] takes any string and applies [[convert_line]] to each line of
the string if the lines are outside our verbatim environment. If they are
inside we just skip them.

<<subroutines>>=
sub web_to_latex {
  local($text) = @_; # read argument into local variable
  local($output) = "";
  local($inverb) = 0;
  while ($text) { 
    $text =~ /^([^\n]*\n)/;
    $text = $';
    $currline = $1;
    if ( $currline =~ s/\\begin\{Mverb\}/\\begin\{verbatim\}/ ) {
      $inverb = 1; $output .= $currline;
    }
    elsif ( $currline =~ s/\\end\{Mverb\}/\\end\{verbatim\}/ ) {
      $inverb = 0; $output .= $currline;
    }
    elsif ( $inverb ) {
      $output .= $currline;
    }
    else {
      $output .= &convert_line($1);
    }
  } 
  return $output;
}

<<conversion subroutines>>

@ \subsection{The Lowlevel Manual Commands}

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

@ \subsubsection{Parsing the Code Unit}

A (standard) function definition or declaration has 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\\
the initializer =0 ; (for pure virtual functions ).\\

\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/\/\/.*\n//g;    # remove C++ comment
$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/= *0 *; *$//;
             # removes = 0 ;
$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 ::

@ 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,)* class S>- and then all
qualifiers. If we find a static qualifier we record that fact.

<<>>=
$code_unit  =~ s/template *<[ ,\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
&apply_Msubst(*code_unit);

&print_debug("code unit at start = $code_unit"); #DEBUGOUT


@ 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.

<<>>=
&print_debug("code unit before cleaning = $code_unit");
$conversion = ($code_unit =~ /operator\s*\w+\s*\(\s*\)/); 
if ($code_unit =~ /\( *\) *\(.*\)/) { 
  $code_unit =~ s/\( *\) *\((.*)\)//; 
  $par_list = $1;
}
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

&print_debug("code unit after first clean up = $code_unit");
&print_debug("par_list = $par_list");

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;
    while ($type =~ s/^ //) {}
    while ($type =~ s/ $//) {} # remove beginning and trailing blanks
    if (($type =~ /^\s*const/) 
        && ($constref eq "no")) {  # remove const & bracket
      $type =~ s/^\s*const//; 
      $type =~ s/ *\& */ /;
    }
    $type =~ s/ *\& */\& /g;
  }
}


@ \subsubsection{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 \&. How do I recognize a 
const \& pair? I look for an occurrence of const followed by a blank followed
by anything followed by \&.

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] =~ /\(.*<.*\)/) &&
         (($params[$i]=~tr/</</) > ($params[$i]=~tr/>/>/))) {
    # append all comma separated parameter parts together
    # as part of a template type list or comma separated
    # init parts, the second condition allows initialization
    # by bracketed expressions containing < or <<
    $params[$i] .= "," . $params[$j]; $j++;
  }
  if (($params[$i] =~ /const .*\&/) && ($constref eq "no")) {
    $params[$i] =~ s/ *const //;
    $params[$i] =~ s/ *\& */ /; # replace blanks&blanks by a single blank
    # $params[$i] =~ s/\&//;     simply remove & if not followed by a 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 . ")";

&print_debug("fname = $fname");
&print_debug("signature = $signature");

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 =~ /^funobjl?$/) {
  <<Mfunobj>> 
  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 || 
    ($funcname =~ /$filter/)) {
  &print_function(); 
}

@ \subsubsection{Mfunc}

<<Mfunc>>=
if ($operator || $constructor || $conversion || $static) {
  &print_warning("Mfunc applies only to functions " .
	         "and not to operators,... ");
}
$prefix = "";
$funcname = $fname;
$postfix = $par_list;
if ($filter eq "all" || $filter eq $currentsection || 
    ($funcname =~ /$filter/) ) {
  &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{Mfunobj}

<<Mfunobj>>=
if ($operator || $constructor || $conversion || $static) {
  &print_warning("Mfunobj applies only to function objects " .
	         "and not to operators,...");
}
$prefix = "";
$funcname = $fname;
$postfix = $par_list;
if ($filter eq "all" || $filter eq $currentsection || 
    ($funcname =~ /$filter/) ) {
  &print_function("extract return type from Mcomment"); 
}
     
@ \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 =~ /$fname/ || $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 || 
    ($fname =~ /$filter/)) {
 &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();
}


@ \subsubsection{Member Types}
In this case we want to document the existence of a type in
the local scope. Such a type can be the result of a typedef
or the definition of a local class.
In the second case we only want to document the existence of a type.
Which is stored in [[\$type]] to be output in [[print_typemember]].

<<typemember>>= 
<<common type code unit cleanup>>
if ( $code_unit =~ s/^ *typedef// ) {
  $code_unit =~ s/typename//g;
  if ( $code_unit =~ /<.*>/ ) {
    $code_unit =~ s/^ *(.*\>\S*) +(\S*)//; 
    # search for last > and then for end of type
    $type = $2; 
  }
  else {
    $code_unit =~ s/^ *(\S*) +(\S*)//;
    $type = $2; 
  }
}
elsif ( $code_unit =~ /(^class|.* +class) +(\w*)/ ) {
  $type = $2; # extract class name
}
else {
 &print_warning("Typemember should be a typedef or a class");  
}
&print_typemember();


@ \subsubsection{Typedef Documentation}
We also want to offer a scheme for typedef documentation. This one actually
shows the source type and the target type, for example in traits classes.
Mcomment is Ltext at this point and [[\$code_unit]] contains the code. It
should be of the form [[typedef type1 type2;]]. The parsing is almost
trivial. Note that type1 could contain nested template parentesis and therefore
also spaces.

<<typedef>>= 
<<common type code unit cleanup>>
if (!($code_unit =~ s/^ *typedef//)) {
  &print_warning("Typedef should start with keyword typedef");
}
if ( $code_unit =~ /<.*>/ ) {
  $code_unit =~ s/^ *(.*>\S*) +(\S*)//; 
  # search for last > and then for end of type
  $type = $1; 
  $fname = $2;
}
else {
  $code_unit =~ s/^ *(\S*) +(\S*)//;
  $type = $1; 
  $fname = $2;
}
&print_typedef();


<<common type code unit cleanup>>=
if ($code_unit =~ /\/\*/) {      # commented code units
  &print_warning("code unit contains a comment. ".
  "I remove the lines containing /* and */.");
  $code_unit =~ s/ *\/\*//;  # remove start comment
  $code_unit =~ s/ *\*\/ *//;    # remove end comment
  $original_code_unit = $code_unit;
}
$code_unit =~ s/\t/ /g;    # replace tabs by blanks
$code_unit =~ s/\/\/.*//g; # remove trailing comment
$code_unit =~ s/\n/ /g;    # replace newline by blank
$code_unit =~ s/; *$//;    # replace; plus blanks at end


@ \subsubsection{Enumeration Types}
Mcomment is Ltext at this point and [[\$code_unit]] contains the code. It
should be of the form [[enum type { t1, ..., tk}]]. The parsing is trivial.
<<enum>>= 
<<common type code unit cleanup>>
if (!($code_unit =~ s/^ *enum//)) {
  &print_warning("Enum should start with keyword enum");
}
$code_unit =~ s/^ *(\w*) *\{//;    # remove blanks type blanks {
$type = $1;
$code_unit =~ s/\} *$//;           # remove } at end
$par_list = $code_unit;
&remove_enclosing_blanks($par_list);
$par_list =~ s/ *, */ , /g;
&print_enum();


@ \subsection{Creating the Output File}
\subsubsection{Printing 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
Mfunobj                   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.

In HTML-mode we need to do two things.
\begin{itemize}
\item Add \verb-\htmlnormallink{typename}{URL}- for all typenames in the 
[[namereplacementtable]].
\item Perform HTML like quoting. Type name and signature consist only of
alphanumeric characters, round brackets ( and ), angular brackets < and >,
kommas, and ampersands (\&).
\end{itemize}
Typenames are maximal substrings of alphanumeric characters.

<<subroutines>>=

sub print_function{
@args = ("funcname","prefix","postfix","signature","type");
# foreach $arg (@args) { &apply_Msubst(*$arg); }  # done earlier

local($getreturntype) = @_;
if ( "$getreturntype" ne "" ) {
  local($rtype) = $Mcomment;
  $rtype =~ s/\s*\{([^\}]*)\}(.|\n)*/$1/;
  $Mcomment =~ s/\s*\{[^\}]*\}(.*)/$1/;
  $type = $rtype;
}

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

if ($mode =~ /HTML/) {
  if ($funcname) { 
    $signature = $prefix . $funcname . "(". $postfix. ")";
  }
  local($semantics) = &substitute_for_placeholders($Mcomment);
  $semantics = &convert_HTML($semantics);
  local($shortsig) = 1;

  if (length($signature) > 25) {
    $shortsig = 0;
  }
  $type = &insert_URLs_and_quote($type);
  $signature = &insert_URLs_and_quote($signature);
  &opentabular(3);

  if ($shortsig == 1) {
    print OUTPUT $type , "\\ \\ \\ \\ \& ", $signature;
    print OUTPUT "\\ \\ \\ \\ \& " , $semantics , "\\\\ \n"; 
  }
  else {
    print OUTPUT $type;
    print OUTPUT "\\ \\ \\ \\ \& \\multicolumn\{2\}\{l\}\{$signature\}\\\\ \n";
    print OUTPUT " \&  \& $semantics\\\\ \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 =~ /^funobjl?/ || $command =~ /^staticl?/ ||
    $command =~ /^conversion?/) {
  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";
}

@ \subsubsection{Printing a Constructor}
We output \verb-\create {Mname} {Mvar} {par_list} {Mcomment}-

<<subroutines>>=
sub print_constructor{
local($Mname_save) = $Mname;
if (!$Mvar || !$Mname ) {
  &error_handler("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";
  $Mname= $Mname_save;
  return;
}
if ($mode =~ /HTML/) {
  local($semantics) = &substitute_for_placeholders($Mcomment);
  $semantics = &convert_HTML($semantics); 
  $sig1 = &insert_URLs_and_quote($Mname);
  $sig2 = $Mvar;
  if ($par_list) { $sig2 .= "(" . $par_list. ")"; }
  local($shortsig) = 1;
  if (length($sig2) > 25)
  { $shortsig = 0; }

  $sig2 = &insert_URLs_and_quote($sig2);
  &opentabular(3);

  if ($shortsig == 1)
  { print OUTPUT "$sig1 \& $sig2; \& " , $semantics , "\\\\ \n\n"; }
  else {
    print OUTPUT "$sig1 \& \\multicolumn\{2\}\{l\}\{$sig2;\}\\\\ \n";
    print OUTPUT " \&  \& $semantics\\\\ \n"; 
  } 

  $Mname= $Mname_save;

  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";
$Mname = $Mname_save;
}

@ \subsubsection{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";
  }
   
  if ($mode =~ /HTML/) {
    local($semantics) = &substitute_for_placeholders($Mcomment);
    $semantics = &convert_HTML($semantics);
    print OUTPUT "~", $Mname ,"() \&" , $semantics ,"\\\\ \n\n";
  }

  $Msubstname = $Mname;
  $arg1 = &convert_M($Msubstname);
  $arg2 = &convert_text($Mcomment);
  local($text) = "\\destruct" .' {'. $arg1 ."\}\n\{". $arg2 ."\}\n";
  print OUTPUT $text,"\n\n";
}


@ \subsubsection{Printing an Enum}

[[\$type]] contains the type, [[\$par_list]] contains the alternatives, and
[[\$Mcomment]] contains the text.  We output \verb-\enum{type}{par_list}-. The
typesetting is done via a latex macro.

<<subroutines>>=
sub print_enum{
@args = ("par_list","type");
if ($mode eq "Fman") {
  print "enum $type \{ $par_list \}\n" ;
  if ($showsem == 1) 
  { print &substitute_for_placeholders($Mcomment) , "\n\n"; }
  return;
}

$arg1 = $type;
$arg1 =~ s/_/\\_/g;  # quote underscores

$arg2 = &convert_M($par_list);

$arg3 = "";
if ($Mcomment && $showsem == 1) 
{$arg3 = &convert_text($Mcomment);}
$text = "\\enum\{$arg1\}\n\{$arg2\}\n\{$arg3\}\n\n";
print OUTPUT $text;
}


@ \subsubsection{Printing a Typedef}
[[\$type]] contains the type, [[\$fname]] contains the new type, and
[[\$Mcomment]] contains the text.  We output
\verb-\typedef{type}{fname}{Mcomment}- or 
\verb-\typemember{type}{Mcomment}- . The typesetting is done via a 
latex macro.

<<subroutines>>=
sub print_typedef{
if ($mode eq "Fman") {
   print "typedef $type $fname\n" ;
   if ($showsem == 1) {
     print &substitute_for_placeholders($Mcomment) , "\n\n"; 
   }
   return;
}
if ($mode =~ /HTML/) {
  $signature = "typedef  $type  $fname ";
  local($semantics) = &substitute_for_placeholders($Mcomment);
  $semantics = &convert_HTML($semantics);
  local($shortsig) = 1;
  if (length($signature) > 25) {
    $shortsig = 0;
  }
  $signature = &insert_URLs_and_quote($signature);
  &opentabular(2);

  if ($shortsig == 1) {
    print OUTPUT $signature , "\\ \& \\ " , $semantics , "\\\\ \n";
  }
  else {
    print OUTPUT "\\multicolumn\{2\}\{l\}\{$signature\}\\\\ \n";
    print OUTPUT " \& $semantics\\\\ \n"; 
  } 
  return;
}

$arg1 = &convert_M($type);
$arg2 = &convert_M($fname);
$typedeftext = "";
if ($Mcomment && $showsem == 1) {
  $typedeftext = &convert_text($Mcomment);
}
$text = "\\typedef\{$arg1\}\{$arg2\}\n\{$typedeftext\}\n\n";
print OUTPUT $text;
}

sub print_typemember{
if ($mode eq "Fman") {
  print "$type\n" ;
  if ($showsem == 1) {
    print &substitute_for_placeholders($Mcomment) , "\n\n"; 
  }
  return;
}
if ($mode =~ /HTML/) {
  $signature = "$type ";
  local($semantics) = &substitute_for_placeholders($Mcomment);
  $semantics = &convert_HTML($semantics);
  local($shortsig) = 1;
  if (length($signature) > 25) {
    $shortsig = 0;
  }
  $signature = &insert_URLs_and_quote($signature);
  &opentabular(2);
  if ($shortsig == 1) {
    print OUTPUT $signature, "\\ \& \\ " , $semantics , "\\\\ \n";
  }
  else {
    print OUTPUT "\\multicolumn\{2\}\{l\}\{$signature\}\\\\ \n";
    print OUTPUT " \& $semantics\\\\ \n"; 
  } 
  return;
}

$arg1 = &convert_M($type);
$typedeftext = "";
if ($Mcomment && $showsem == 1) {
  $typedeftext = &convert_text($Mcomment); 
}
$text = "\\typemember\{$arg1\}\n\{$typedeftext\}\n\n";
print OUTPUT $text;
}


@ \subsection{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 =~ /HTML/)
{ &closetabular(); }
if ($mode eq "HTMLman") {
  &closetabular();
  print OUTPUT "\\end{document}\n"; 
}
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_info("Preparing manual page with LaTeX...");

  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" . $dontshowinfo);
  if ($latexruns == 2) {
    system ("latex /tmp/" . $pid . "-ext.tex" . $dontshowinfo);
  }

  if ($xdvi eq "yes") {
    &print_info("Starting xdvi previewer...");
    system ("xdvi -s 3 /tmp/" . $pid . "-ext.dvi" . $dontshowinfo);
  }
  elsif ($dvioutfile ne "") {
    &print_info("Copying dvi file into file $dvioutfile in working directory...");
    system("cp /tmp/$pid-ext.dvi $owd/$dvioutfile");
  }
  else {
    &print_info("Copying dvi file into file $basename.dvi in working directory...");
    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") {
  close OUTPUT;
  open OUTPUT , ">>/tmp/$pid-ext.tex";
  print OUTPUT "\\end{manual}\n"; 
  close(OUTPUT); 

  &print_info("  Created $basename.man");
  &print_info("Removing the manual comments (except for Mpreamble) from $INPUT...");

  $tempfile = "/tmp/" . $pid . "-$basename";
  if ($delman eq "refined") {
    system("ext_ldel $INPUT $tempfile.$ext");
    &print_info("  Created $tempfile.$ext through ext_ldel");
  }
  if ($delman eq "yes" || $kind eq "Cweb") {
    if ($delman eq "no") 
    { &print_info("Option delman=no not implemented for Cweb");}
    system("ldel $INPUT $tempfile.$ext");
    &print_info("  Created $tempfile.$ext through ldel");
  }
  if ($delman eq "no" && $kind ne "Cweb") {
    system("cp  $INPUT $tempfile.$ext"); 
    &print_info("  Created $tempfile.$ext by copying");
  }

  system("mv /tmp/$pid-ext.tex $basename.man");  # move manpage
  &print_info("Calling $kind weave on $tempfile.$ext...");
  # 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");
  }
  elsif ($kind eq "Lweb") {
    system( "lweave $tempfile $noweaveoptions");
    system( "mv $tempfile.tex $basename.tex");
    system( "mv $tempfile.nw $basename.nw");
  }
  elsif ($kind eq "noweb") {
    system("noweave -delay $noweaveoptions $tempfile.nw > $basename.tex");
  }

  &print_info("  Created $basename.tex");
  if ($latexruns == 0) {exit;}
  &print_info("Calling latex...");
  system("latex $basename.tex $dontshowinfo");
  if ($latexruns == 2) {
    system("latex $basename.tex $dontshowinfo");
  }
  if ($xdvi eq "yes") {
    &print_info("Starting xdvi previewer...");
    system("xdvi -s 3 $basename.dvi $dontshowinfo");
  }
  system("rm -f /tmp/$pid*");

}

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

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


@ \subsection{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. Print\_info displays progress information if switched on.

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

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

sub print_info {
  if ($informational eq "yes") {
    local($text) =  @_;  # read argument into local variable
    print "$text\n\n";
  }
}

sub print_debug {
  if ($debugging eq "yes") {
    local($text) =  @_;  # read argument into local variable
    print "DEBUG $text\n";
  }
}

@ \subsection{Helpers and Subroutines}
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;   
  }
}


@ In HTML-mode we need function to open and close tabulators. We have a global
variable [[\$HTMLopentabulator]] which tells us whether a tabulator is open.

<<subroutines>>=

sub opentabular{
 local($cols) = @_;  # this is either two, three or four
 if ($HTMLopentabular eq "no") {
   if ($cols == 2) {
     print OUTPUT "\\begin{tabular}{ll}\n"; }
   elsif ($cols == 3) {
     print OUTPUT "\\begin{tabular}{lll}\n"; }
   elsif ($cols == 4) {
     print OUTPUT "\\begin{tabular}{llll}\n"; }
   else {
     &error_handler("open_tabulator expects argument 2 or 3"); 
   }
   $HTMLopentabular = "yes";
 }
}

sub closetabular{
 if ($HTMLopentabular eq "yes") {
   print OUTPUT "\\end{tabular}\n\n";
   $HTMLopentabular = "no";
 }
}


@ \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) = "";
  local($lastchar) = chop($text);
  if ($lastchar eq "\n" || $lastchar eq "\r") { }
  else { $text .= $lastchar; }  #last line of text maybe without linefeed 
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 = $';
      $output .= "\|\|";
    } 
    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.

On March 6th, I made the following change. I want that indentifiers 
that consist of a single symbol are typeset as in math mode. Therefore 
I only put identifiers of more than one symbol into mathit. 

<<conversion subroutines>>=

# the following procedure is copied from ext.nw. Please make changes only here.
# I still need a 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");
              print STDERR $Ctext;}
            $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 { if ( length($ident) > 1 ) 
                  { $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;
   if ($Ctext =~ /<.*>/)
   { # I guess that I discovered template brackets. Therefore, I interpret
     # all brackets in the text as template brackets and I keep the spacing
     # in the input.
     $Ctext =~ s/</\\Ltemplateless/g;
     $Ctext =~ s/>/\\Ltemplategreater/g;
   }
   else
   { # there are no template brackets. I interpret < and > as in Latex and 
     # leave the spacing to LATEX
     $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;
   $Ctext =~ s/\-\-/\\Dminus /g;
   # $Ctext =~ s/!=/\\Noteq /g;
   $Ctext =~ s/\\Lle/\\Lle /g;
   $Ctext =~ s/\\Lge/\\Lge /g;
   $Ctext =~ s/\\Leq/\\Leq /g;
   $Ctext =~ s/\\Ltemplateless/\\Ltemplateless /g;
   $Ctext =~ s/\\Ltemplategreater/\\Ltemplategreater /g;
   $Ctext =~ s/\\Larrow/\\Larrow /g;
   #if ($Ctext =~ /</) 
   #{ while ($Ctext =~ /^(.*)<([^<>]*)>(.*)$/) # innermost template brackets
     #{ local($C1) = $1;
     #  local($C2) = $2;
     #  local($C3) = $3;
     #  if ($C2 =~ /\\Lless/) # template arg is template
     #  { $C2 =  "\\ " . $C2; } # insert blank after < 
     #  if ($C3 =~ /^>/)  # this > is followed by >
     #  { $C3 = "\\ " . $C3; } #insert blank before >
     #  $Ctext = $C1. "\\Lless " . $C2. "\\Lgreater " . $C3;

       # $Ctext =~ s/</\\Lless /g; 
       # $Ctext =~ s/>(\S)/\\Lgreater \\ $1/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;
}


@ \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{Procedure Convert\_HTML}

We want to remove quoted code and mathmode from the input and we want to deal
with labels.  We first remove quoted code and then remove math-mode. Finally we
deal with the labels.

<<conversion subroutines>>=

sub convert_HTML{
 local($Ctext) = @_; # read argument into local variable
 $Ctext =~ s/\\begin\{Mverb\}/\\begin\{verbatim\}/g;
 $Ctext =~ s/\\end\{Mverb\}/\\end\{verbatim\}/g;
 $Ctext = &remove_quoted_code($Ctext);
 $Ctext = &remove_math_mode($Ctext);
 $Ctext = &deal_with_refs($Ctext);
 return $Ctext;
}

@ \subsubsection{Removing Quoted Code in Conversion to HTML}

I am reusing the code from 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.

The code can be simplified since we are aiming for conversion to plane ASCII
and not to LaTex. Essentially I only have to recognize quoted code, to remove
the brackets, and to quote some special characters (namely \_ and \&). In other
word I am reusing the code but call
[[quote_special_symbols_in_quoted_code_removal]] instead of [[convert_M]].

<<conversion subroutines>>=

sub remove_quoted_code{
  local($text) = @_; # read argument into local variable
  local($output) = "";
  $text =~ s/\n/LEDANEWLINE/g;

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 .= &quote_special_symbols_in_quoted_code_removal($`);    
         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 .= &quote_special_symbols_in_quoted_code_removal($`);
         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 = $';
    }
  $output =~ s/LEDANEWLINE/\n/g;
  return $output ;
}

sub quote_special_symbols_in_quoted_code_removal{
  local($text) = @_;
  $text =~ s/_/\\_/g;
  $text =~ s/&/\\&/g;
  return $text;
}



@ \subsubsection{Removing Math-Mode in Conversion to HTML}

I am not touching any display math mode. Displayed math is started by \verb+\[+
and ended by \verb+\]+. So if the text contains displayed math I simply return
it.  This is to simplistic as the text may contain [[\\]] outside the displayed
math.  This is not allowed in a tabular. I leave it for manual
treatment. Moreover, latex does not like displayed math in a tabular
environment.  My new strategy is to simpy delete displayed math and warn the
user that he is supposed to edit the file manually.

For mathmode we search for the first two occurrences of \$.  We take the stuff
between the dollars and try to convert it. If we do not succeed we put it back
in and report our failure in file [[unrecognizedmath]].

We follow a very simple strategy to remove math. We first treat
\verb+\Labs,\mbox,\Litem,\Lvert,\ + and then we apply all the replacements in
the texreplacementtable. If this removes all occurrences of \verb+\+ we claim
success.

For the occurance of [[\\]] in the [[\$semantics]] string we follow the
following rule. If we are to end within a tabular row which is the case in any
creation, destruction, function comment we put in a rawhtml line break via the
call to [[quote_special_symbols_in_text_mode]]. For all tabular structures
which need the linebreak symbols like [[eqnarray]] and  [[array]] we keep
them in the string for the latex run over the manual page.

<<conversion subroutines>>=
sub remove_math_mode{
 local($Ctext) = @_; 
 $Ctext =~ s/\n/LEDANEWLINE/gi;

 if ( $Ctext =~ /array/  || $Ctext =~ /tabular/ ) {
   local($unprocessed) = $Ctext;
   local($transformed) = "";
   while ( $unprocessed =~ s/\\end\{([^\}]*)\}(.*)// ) {
     local($latexenv) = $1;
     local($rest) = $2;
     if ( $latexenv =~ /array/ || $latexenv =~ /tabular/ ) { 
       local($lenv) = $latexenv; $lenv  =~ s/\*/\\\*/; # escape * environments
       $unprocessed =~ s/\\begin\{$lenv\}(.*)//e;
       local($between) = $1;
       # now $unprocessed $between $rest is the whole line
       $between =~ s/\\\\/LEDAARRAYNL/gi;
       $transformed .= ($unprocessed . "\\begin{$latexenv}" . $between .
                        "\\end{$latexenv}");
       $unprocessed = $rest;
     }
     else {
       $transformed .= ($unprocessed . "\\end{$latexenv}");
       $unprocessed = $rest;
     }
     if ( 0 ) { # debug on or off
       print "\nXXXXXXXXXXXXXXXXXXXX\n";
       print $transformed;
       print "\nXXXXXXXXXXXXXXXXXXXX\n";
       print $unprocessed;
       print "\nXXXXXXXXXXXXXXXXXXXX\n";
     }
   }
   $Ctext = $transformed . $unprocessed;
 }
 
 if (0 || $Ctext =~ /\\\[/ || $Ctext =~ /\$\$/) { # Ctext contains displayed math.
   &print_warning("I encountered displayed mathematics. I replaced it by ordinary math mode");
   $Ctext =~ s/\\\[/\$/g;
   $Ctext =~ s/\\\]/\$/g;
   $Ctext =~ s/\$\$/\$/g;
 }


 local($unprocessed) = $Ctext;
 $Ctext = "";
 
 while ($unprocessed =~ /^([^\$]*)\$([^\$]*)\$(.*)$/) {
     # text contains two or more dollars
     $Ctext .= &quote_special_symbols_in_text_mode($1);
     local($math) = $2;
     local($math_original) = $2;
     $unprocessed = $3;
     # lets first do the complicated stuff
     while ($math =~ s/\\Labs\{([^\}]*)\}/\|$1\|/) {}
     while ($math =~ s/\\mbox\{([^\}]*)\}/$1/) {}
     while ($math =~ s/\\Litem\{([^\}]*)\}/<$1>/) {}
     $math =~ s/\\Lvert/\|/g;
     $math =~ s/\\ / /g;  # protected blank in math mode
     foreach $key (keys(%texreplacementtable)) {
       local($replacement) = $texreplacementtable{$key};
       $math =~ s/\\$key/$replacement/g;
     }
     $math =~ s/\\mathit\{([^\}]*)\}/$1/g;
     # print unprocessed tex commands
     if ($math =~ /\\/) { # unrecognized tex-command
       print UNRECOGNIZEDTEX  $math, "\n\n";
       $Ctext .= "\$" . $math_original . "\$";
     }
     else
     { $Ctext .= &quote_special_symbols_in_math_mode($math); }
 }
 $Ctext .= &quote_special_symbols_in_text_mode($unprocessed);
 $Ctext =~ s/LEDANEWLINE/\n/gi;
 $Ctext =~ s/LEDAARRAYNL/\\\\/gi;
 return $Ctext;
}

@  The following conversion also servers some transformation concerning
HTML typesetting. We replace in case of HTML the complicated command
[[\headerline]] by a simple [[\textbf]] which serves our purposes
perfectly.

<<conversion subroutines>>=
sub quote_special_symbols_in_text_mode {
  local($Ctext) = @_; # read argument into local variable
  # it remains to quote all special characters.
  # $Ctext =~ s/\\\\LEDANEWLINE/\\HTML\{P\}\{\}LEDANEWLINE/g;
  $Ctext =~ s/\\\\/\\HTML\{BR\}\{\}/g;
  $Ctext =~ s/\\headerline/\\textbf/g;
  # stating latex2html 98.1 we can enforce a linebreak
  return $Ctext;
}

sub quote_special_symbols_in_math_mode {
 local($Ctext) = @_; # read argument into local variable
  # it remains to quote all special characters.
 $Ctext =~ s/_/\\_/g;
 $Ctext =~ s/&/\\&/g;
 $Ctext =~ s/\^/\\circumflexop /g;
 return $Ctext;

}


@ [[deal_with_refs]] looks for \verb-\ref-. It replaces it by a
\verb-\hyperref-.  Hyperref takes four arguments. The last argument is the
label. The first argument appears in the html-document. The text output
contains the second argument followed by the numerical reference followed by
the third argument. I set the second and the first argument to the empty
string. Thus [[see section \verb-\ref{graphs}-]] generates 
[[see section graph]] in the html-document and generates 
[[see section number]] in the paper document.

<<conversion subroutines>>=

sub deal_with_refs{
 local($Ctext) = @_; # read argument into local variable
 while ($Ctext =~ /\\ref\{([^\}]*)\}/)
 { local($key) = $1;
   $key1 = $key; $key1 =~ s/_/\\_/g;
   $Ctext =~ s/\\ref\{$key\}/\\hyperref{$key1}{}{}{$key}/;
 }
 return $Ctext;

}


@ [[insert_URLs_and_quote]] is applied to return types and to signatures of
functions.  They consist of strings of alphanumeric characters (including \_),
blanks, round brackets, angular brackets, square brackets, kommas, equality
signs, star, dots, colon, and ampersands. For each maximal alphanumeric
substring that is in the namereplacementtable we need to add an
\verb-\addnormallink{typename}{URL}-. The split character [[&]] need to be
quoted.



<<conversion subroutines>>=

sub insert_URLs_and_quote{
  local($Ctext) = @_; 
  local(@fields) = split(/([ \(\)\<\>\,\&\.\:\[\]=\*])/,$Ctext);
  foreach $i (0 .. $#fields) {
    if ($fields[$i] =~ /^\w*$/) { # alphanumeric string
      local($key) = $fields[$i];
      local($label) = $namereplacementtable{$key};
      if ($label ne "" && $key ne $Mtype) {
        $key =~ s/_/\\_/g;
         $fields[$i] = "\\htmlref\{$key\}\{$label\}"; 
       }
       else {
         $key =~ s/_/\\_/g;
         $fields[$i] = $key;
       }
    }    
    else { # quote some characters
      if ($fields[$i] =~ /&/) {
        $fields[$i] = "\\$fields[$i]"; 
      }
      if ($fields[$i] =~ /</) {
        $fields[$i] = "\$<\$"; 
      }
      if ($fields[$i] =~ />/) {
        $fields[$i] = "\$>\$"; 
      }
      $fields[$i] =~ s/\\n/\\Ln/g;  # takes care of \n
    }
  }
  $Ctext = join("",@fields);
  return $Ctext;
}



@ \subsection{Usage Information}

All utilities give manual information if called without arguments.

<<subroutines>>=
sub print_usage {
if ($mode eq "Lman" || $mode eq "Ldoc") {
  print "Usage is
          $mode 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}
informational={yes,no}
ack={yes,no}
usesubscripts={no,yes}
latexruns={1,2,0}
delman={yes,no}
filter={all,signatures,definition,types,creation,
operations,implementation,example,opname}

$mode can be customized by putting options in a file 
$mode.cfg in either the home directory or the working 
directory.

Call 
      $mode ltools 
        for more information on the tools usage.
      $mode mancommands 
        for a short overview of usable manual commands.\n\n";
}

if ($mode eq "Fman") {
  print "Usage is
          $mode file filter

where the file name is of the form T.[h|w|lw] 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, types, creation, 
   operations, implementation, example, opname }

Call 
      $mode ltools 
        for more information on the tools usage. 
      $mode mancommands 
        for a short overview of usable manual commands.\n\n" ;
}
exit;
}


sub print_mancommands {
if ($mode eq "Lman" || $mode eq "Ldoc" || $mode eq "Fman") {
print "Manpage start header is:

   /*{\\Manpage {DT} {T1,..,Tk} {short_description} [MVAR]}*/
   afterwards common variables are 
   \\Mname = DT<T1,..,Tk>
   \\Mvar =  MVAR

Manual sections are:

   /*{\\Mdefinition specification_text}*/

   /*{\\Mtypes [W]}*/
       /*{\\Mtypedef typedef_documentation}*/
       /*{\\Mtypemember type_documentation}*/
       /*{\\Menum type_documentation}*/

   /*{\\Mcreation [MVAR] [W]}*/
       /*{\\Mcreate constructor_specification }*/
       /*{\\Mdesctruct desctructor_specification }*/

   /*{\\Moperations [W1] [W2]}*/          
       /*{\\Mop semantic_description }*/ 	
       /*{\\Mstatic semantic_description }*/
       /*{\\Mconversion semantic_description }*/
       /*{\\Mbinop semantic_description }*/
       /*{\\Munop semantic_description }*/
       /*{\\Marrop semantic_description }*/ 
       /*{\\Mfunc semantic_description }*/
       /*{\\Mfunop semantic_description }*/
       /*{\\Mfunobj semantic_description }*/
       /*{\\Mbinopfunc semantic_description }*/
       /*{\\Munopfunc semantic_description }*/ 
       /*{\\Mfunobj{return_type} semantic_description }*/
   /*{\\Mimplementation implemenation_information }*/
   /*{\\Mexample example_description }*/

Additional man commands
  /*{\\Mtext some_text }*/
  /*{\\Moptions nextwarning=no }*/
  /*{\\Msubst pattern replacement }*/
Common tex macros for man comments are 
  \\setopdims[2], \\precond[1], \\headerline[1]
Verbatim code in example section with environment 
  \\begin|end{Mverb}.\n\n"; 
}
exit;
}

sub print_ltools {
$owd = $ENV{"PWD"};
chdir ("/tmp");
local($pid)=$$;
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 "\\usepackage\{html\}";
  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 $dontshowinfo");
  system ("xdvi /tmp/$pid-ext.dvi $dontshowinfo");
  system ("rm -f /tmp/$pid-ext.*");
}
chdir ("$owd");
exit;
}


@ \section{The \LaTeX-Macro Files}
<<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>>
<<enumerations and typedefs>>
<<old macros>>

@ \subsection{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>>=
\newcounter{manctr}
\newenvironment{manual}{
\setcounter{manctr}{1}
\baselineskip 3.0ex   
%\spaceskip  .4em plus .25em minus .25em
%\xspaceskip .65em
\parskip 11pt plus 1pt minus 1pt
\parindent 0pt
}{}


@ \subsection{ \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.2ex} 
%additional space between entries

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

\newlength{\typewidth} \setlength{\typewidth}{0.15\textwidth}    
\newlength{\longtypewidth} \setlength{\longtypewidth}{0.4\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}
       }

\newcommand{\setopdims}[2]{
  \setlength{\typewidth}{#1}  %\typewidth=#1cm
  \setlength{\callwidth}{#2}  %\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{\returntype}{\,}

\newcommand{\function}[4]{
   \setlength{\checkwidth}{\typewidth}
   \renewcommand{\returntype}{#1}   
   \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 > \longtypewidth}
       {\parbox[t]{\textwidth}{#1}\\
       \renewcommand{\returntype}{\ }
        \settowidth{\actualtypewidth}{\returntype}
        \addtolength{\actualcallwidth}{\colsep}
       }
       {} %empty else case
       \ifthenelse{\actualtypewidth > \typewidth}
       {
        \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}{\returntype}\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 \returntype}%
       \parbox[t]{\callwidth}{\raggedright \sloppy  #2(#3)}%\hspace{\colsep} 
       \parbox[t]{\descriptwidth}{\sloppy  #4}%
      }%end else
      }%end return 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}{\,}        % was empty before but creates trouble 2html
\newcommand{\createtype}{\,}  % was empty before but creates trouble 2html
\newlength{\actualtypeplusnamewidth}
\newlength{\createtypewidth}

\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{\createtypewidth}{#1}
	      \ifthenelse{\createtypewidth > \longtypewidth}
	      {\parbox[t]{\textwidth}{#1}\\
               \ifthenelse{\equal{#3}{}}%
               {\renewcommand{\decl}{\hspace*{\typewidth}#2;}}%
               {\renewcommand{\decl}{\hspace*{\typewidth}#2(#3);}}
              }{}
   \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 
       }

@ \subsection{Enumerations and Typedefs}

For the enums we have three arguments, the type, the list of alternatives, and
the text.  We put the first two arguments centered on a line and add the text
below.

<<enumerations and typedefs>>=
\newlength{\actualenumwidth}

\newcommand{\enum}[3]{%
\settowidth{\actualenumwidth}{enum #1\ \{\ #2\ \}}
\ifthenelse {\actualenumwidth > \declwidth}{
\noindent\parbox[t]{\textwidth}{%
\parbox[t]{\textwidth}{enum #1\ \{\ #2\ \}}\vspace{\rowsep}\\%
\hspace*{1cm}\hfill\parbox[t]{\createtextwidth}{\sloppy #3}%
}}% else
{\noindent\parbox[t]{\declwidth}{enum #1\ \{\ #2\ \}}%
\parbox[t]{\createtextwidth}{\sloppy #3}%
}\par}

\newcommand{\typemember}[2]{%
\settowidth{\actualenumwidth}{#1}
\addtolength{\actualenumwidth}{\colsep}
\ifthenelse {\actualenumwidth > \declwidth}{
\noindent\parbox[t]{\textwidth}{%
\parbox[t]{\textwidth}{#1}\vspace{\rowsep}\\%
\hspace*{1cm}\hfill\parbox[t]{\createtextwidth}{\sloppy #2}%
}}
{\noindent\parbox[t]{\declwidth}{#1}%
\parbox[t]{\createtextwidth}{\sloppy #2}%
}\par}

\newcommand{\typedef}[3]{%
\settowidth{\actualenumwidth}{typedef #1 #2}
\ifthenelse {\actualenumwidth > \declwidth}{
\noindent\parbox[t]{\textwidth}{%
\parbox[t]{\textwidth}{typedef #1 #2}\vspace{\rowsep}\\%
\hspace*{1cm}\hfill\parbox[t]{\createtextwidth}{\sloppy #3}%
}}% else
{\noindent\parbox[t]{\declwidth}{typedef #1\ #2\ }%
\parbox[t]{\createtextwidth}{\sloppy #3}%
}\par}


@ \subsection{Items and Accronyms}

<<items and such>>=
\newcommand{\CC}{C\raise.06ex\hbox{\tt ++}}
\newcommand{\CCC}{C\raise.08ex\hbox{\tt ++}}
\newcommand{\gpp}{g\hbox{\tt ++\ }} 
\newcommand{\nat}{\hbox{\rm\vrule\kern-0.045em N}}
\newcommand{\real}{\hbox{\rm\vrule\kern-0.035em R}}
\newcommand{\sset}[1]{\{\hspace{0.05em}#1\hspace{0.05em} \}}
\newcommand{\set}[2]{ \left\{\hspace{0.1em} #1 \mbox{ ; } #2 \hspace{0.1em} \right\}}
\newcommand{\range}[2]{[#1 \, .. \, #2]}

\newcommand{\precond}{{\it Precondition}: }
\newcommand{\Labs}[1]{\hbox{$|\,#1\,|$}}
\newcommand{\Lvert}{|}
\newcommand{\Litem}[1]{\hbox{$\langle #1 \rangle$}}
\newcommand{\Lchunk}[1]{$\langle${\it #1}$\rangle$}


@ \subsection{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\par
\parbox[t]{\textwidth}{{\bf #1}}\par
\nopagebreak
}
%empty line before bracket is crucial 

\newcommand{\definition}{
\setcounter{manctr}{1}
\headerline{\arabic{manctr}. Definition}
\stepcounter{manctr}}

\newcommand{\creation}{
\headerline{\arabic{manctr}. Creation}
\stepcounter{manctr}}

\newcommand{\types}{
\headerline{\arabic{manctr}. Types}
\stepcounter{manctr}}

\newcommand{\operations}{
\headerline{\arabic{manctr}. Operations}
\stepcounter{manctr}}

\newcommand{\implementation}{
\headerline{\arabic{manctr}. Implementation}
\stepcounter{manctr}}

\newcommand{\example}{
\headerline{\arabic{manctr}. Example}
\stepcounter{manctr}}

@ \subsection{Special Symbols}

And here are the corresponding \TeX\ commands.

<<special symbols>>=
\newcommand{\Lless}{\hbox{\tt <}}
\newcommand{\Lgreater}{\hbox{\tt >}}
\newcommand{\Ltemplateless}{\hbox{\tt <}}
\newcommand{\Ltemplategreater}{\hbox{\tt >}}
\newcommand{\<}{\hbox{\tt <}}
\renewcommand{\>}{\hbox{\tt >}}
\newcommand{\underscore}{_}
\newcommand{\Lle}{\le}
\newcommand{\Lge}{\ge}
\newcommand{\Dplus}{{++}}
\newcommand{\Dminus}{{--}}
\newcommand{\Lass}[1]{\mathrel{{#1}{=}}}
\newcommand{\Lminuseq}{{-}{=}}
\newcommand{\Noteq}{{!}{=}}
%\newcommand{\Leq}{\equiv}
\newcommand{\Leq}{\mathbin {{=}{=}}}
\newcommand{\Larrow}{\rightarrow}
\newcommand{\tildeop}{{\sim}}
\newcommand{\Tildeop}{{\char126}}
\newcommand{\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}{@$\Lless\Lless$}           % geaendert von \<\<
\newcommand{\KGG}{@$\Lgreater\Lgreater$}
\newcommand{\DLK}{{\tt [[}}
\newcommand{\DRK}{{\tt ]]}}
\newcommand{\Ln}{ \mbox{$\backslash${\tt n}} } 


@ \subsection{Old Macros}

Some of the stuff that follows can be purged.

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

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

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

\newcommand{\n}{\backslash n}

\newcommand{\co}{\mbox{//}}



% LEDA macros:

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


% verbatim

\font\ttbig= cmtt10 scaled \magstephalf

\chardef\other=12
\newcommand{\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{Additional Scripts - Pre and Postprocessing}
\subsection{Cleaning up Manual Comments - ldel and ext\_ldel}
[[ldel infile outfile]] reads a file, deletes all manual comments from it
(except Mpreamble comments) and writes the output to outfile.

<<ldel>>=
#!/bin/sh -f
perl $LEDAROOT/Manual/cmd/ldel.pl $1 $2

<<ldel.pl>>=
<<subroutines>>

$INPUT = $ARGV[0] && shift;
$OUTPUT = $ARGV[0];
if ($OUTPUT eq "") {
  print "
Usage is
          ldel infile outfile              

Removes manual comments from infile.\n";
  exit;
}

open (INPUT) || die "Error: 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/ || / *\/\*\{\\X/ ) {
    # 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));
    }
  }
  elsif ( / *\/\*.*Mkillcomment/ ) { 
    while ($_ && (! ( /\*\// ))) {
      $_ = <INPUT>; 
    }
  }
  else {
    print OUTPUT $_; 
  }
}
  
close(OUTPUT);

@ On November 5, 96 I extendend delman. I added the possiblility to leave the
manual comments in the code and to typeset them using LaTeX. 
I use the following strategy. Whenever I see a comment of the form
\verb-/*{\M ... }*/- or \verb-/*{\X ... }*/ which is followed by C-code
I output
\begin{verbatim}
@ \semantics{ ... }

<<chunk>>=

\end{verbatim}
where chunk is the currently defined chunk and whenever I see a comment of
the form above which is followed by non-C-text, i.e., by [[@ ]] or
by [[<<chunkname>>=]], I output
\begin{verbatim}
@ \semantics{ ... }
\end{verbatim}

This is strategy is easily implemented by a finite automaton.  I read the input
file line by line. Whenever I encounter a chunk definition line [[<<....>>=]] I
remember the line. Whenever I find a comment I read the comment in full.  If it
is a preamble comment I output it, if it is a text comment I ignore it and
otherwise I output \verb-\semantics{...}-. I continue reading until I find the
first non-empty line after the manual comment. If it begin with [[@ ]] or with
[[<<...>>=]] I am in ground state again. If not I print the chunk definition
line and continue.


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

<<ext_ldel.pl>>=

<<subroutines>>

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

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

              ldel infile outfile              

removes manual comments from infile\n";
  die;
}

$chunk_name = "";

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

while (<INPUT>) {
  ground_state:
 
    $Mpreamble = 0;
    $Mignore = 0;
    $Manpage = 0;

    if (/\<\<.*\>\>=/) {  # we read a chunk name and remember it
      $chunk_name = $_;
      print OUTPUT $_;
      next;
    }
        
    if ( / *\/\*\{\\M/ || / *\/\*\{\\X/) {
      # current line contains the begin of a manual comment
      # we determine whether we are dealing with a preamble comment
      # or a text comment
      # and we delete the header of the comment
      if ( /Mpreamble/ ) { $Mpreamble = 1; }
      if ( /Mtext/ || /Manpage/ || /Mdefinition/ || /Mtypes/ || 
           /Moperations/ ||/Mimplementation/ || /Mcreation/ || 
	   /Moptions/ || /Msubst/ || /Mexample/ )    
      { $Mignore = 1; }

      if ( /Manpage/ ) { 
        $Manpage = 1; 
	$Manpageline = $_;

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

        s/ *\/\*\{\\\S*//;  # remove the manual comment 

        if ($Manpage == 1) {
           /\{([^\{\}]*)\}\s*\{([^\{\}]*)\}\s*\{([^\{\}]*)\}\s*\{([^\{\}]*)\}/;               
           $Mtype = $1;
           $par_list = $2;
           $title = $3;
           $Mvar = $4;
           if ($par_list =~ /^ *$/) 
           { $Mname = $Mtype; }
           else 
           { # remove excessive blanks in parlist
             $par_list =~ s/ //g;
             $Mname = $Mtype."<".$par_list.">";
           } 
	   $Manpage = 0;
        }
        $Mcomment = "";

        # we scan lines until we find the end of a manual comment
        while ($_ && (! ( /\}\*\// ) ) ) {
          $Mcomment .= $_;
          $_ = <INPUT>; 
        }

        # the current line contains the end of a manual comment 
        s/\}\*\/ *//; 
        $Mcomment .= $_;
        if ($Mpreamble == 1) {
          &print_unit(&convert_text($Mcomment));
          next;
        }
        if ($Mignore == 1) { next; }  # no output 
         
        # we are in the standard case and want to output the appropriate stuff
         
        print OUTPUT "\@ \\semantics{", &convert_text($Mcomment), "}\n";

        $_ = <INPUT>;
        while ($_ && /^\s*$/) {  $_ = <INPUT>; }
      
        # we are in the first non-empty line after the manual comment

        if (!(/^\@/ || /^\<\<.*\>\>=/)) # current chunk is continued
        {  print OUTPUT $chunk_name, "\n"; }
      
        goto ground_state; 
      }
      print OUTPUT $_; 
    }
  
close(OUTPUT);

@ We also need a new manual macro.

<<MANUAL.mac>>=

\newlength{\setspacing}
\newlength{\semwidth}
\setlength{\semwidth}{\textwidth}
\newlength{\semindent}
\settowidth{\semindent}{{\bf Semantics}:\ }
\addtolength{\semindent}{\parindent}
\addtolength{\semwidth}{-\semindent}

\newcommand{\semantics}[1]{
\nopagebreak%\hspace{\codemargin}
{\bf Semantics}:\ \parbox[t]{\semwidth}{#1}
\vspace{2ex}

}

@ \subsection{The lweave Command}
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/sh
if [ "$1" = "" ] 
then
  echo ""
  echo "Usage is"
  echo "          lweave foo[.lw] [noweave_options]"
  echo ""
  echo "Converts an Lweb file foo.lw into a LaTeX file foo.tex."
  exit
fi
file=`basename $1 .lw`
location=`dirname $1`
name="$location/$file"

if [ -f $name.lw ] 
then
  echo "Calling lw2nw on $name.lw ..."
  echo ""
    lw2nw $name.lw > $name.nw
  shift
  echo "Calling noweave -delay on $name.nw $* ..."
  echo ""
    noweave -delay "$@" $name.nw > $name.temp

  echo "Treating empty lines in code and taking care of pagebreaks in $name.tex ..."
  echo ""
    emptyline $name.temp > $name.tex
else
  echo "Error: File $name.lw does not exist."
  echo ""
  exit
fi

<<lw2dvi>>=
#! /bin/sh
if [ "$1" = "" ]  
then
  echo ""
  echo "Usage is"
  echo "          lw2dvi foo[.lw]"
  echo ""
  echo "Converts an Lweb file foo.lw into a dvi file foo.dvi."
  exit
fi
file=`basename $1 .lw`
location=`dirname $1`
name="$location/$file"
if [ ! -f $name.lw ]
then
  echo "Error: File $name.lw does not exist."
  echo ""
  exit
fi

lweave $1

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>>=

<<MANUAL.pagesize>>
<<Lbook.sty>>

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

\let\nowebsize=\small%selects small font for code
%\nwcodetopsep = 3pt plus 1.2pt minus 1pt   so stehts im Orginal
\nwcodetopsep = 10pt plus .5pt minus .5pt

<<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 is
          lw2nw file              

Converts foo.lw to foo.nw.\n";
  exit;
}

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

while (<INPUT>)
{  if (/^\\begin{verbatim}/)
   { # print until I encounter end{verbatim}
     while (! /\\end{verbatim}/ ) { print $_; $_ = <INPUT>; }
     print $_; $_ = <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}";
      if (!$_) { die "Error: File terminated without @ \\end{document}";}           
      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>;
          if (!$_) { die "Error: File terminated without @ \\end{document}";}
        }
      # 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>;
           if (!$_) { die "Error: file terminated without @ \\end{document}";}
        }
     }
   # current line is a text line.
   print &convert_line($_);
}
close(<INPUT>);


  
 

@ \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 an appropriate number of
lines containing only \% after the code chuck.  Such lines have no effect with
respect to LaTeX and 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.  I have to be a
bit careful where I insert the comment lines. I frequently define two code
chucks right after another. I stay in code mode if the line containing
nwendcode not also containes a nwbegincode.

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 is
          emptyline filename\n";
  exit;
}

open (INPUT)  || die "Error: Can't find input file $INPUT: $!\n";
$anzahl = 0;
while (<INPUT>) {
  $codechunk = ""; 
  if (/nwbegincode/) 
    { $line = $_; chop($line);
      print $line,"\\nwcodepenalty=\\Lhighpen\n"; 
      $_ = <INPUT>;
      # $anzahl = 0;           
      while (!/nwendcode/ || /nwbegincode/)
        { 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>);

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


@ \section{Installation Remarks}
To use this package you have to 
\begin{enumerate}
\item set [[LEDAROOT]] to the root directory of your actual LEDA installation.
\item extend your path by [[\$LEDAROOT/Manual/cmd]]
\item extend your TEXINPUTS by [[\$LEDAROOT/Manual/tex]]
\end{enumerate}
The tools are based on
\begin{itemize}
\item Perl >5.0
\item Noweb
\item LaTeX2HTML > 98.1
\end{itemize}


\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.
\item July 20, 96: I extended Fman to allow for approximate searching of opnames. I first do it in a very rudimentary way. I report any operation that
contains the opname argument.
\item July 23, 96: Michael Seel asks for three extensions.
\begin{itemize}
\item he wants to give options to noweave. I introduce noweave options.
They can only be set in the Ldoc.cfg file. 
\item Msubst is not gereral enough. He wants be able to replace
[[CGAL_Integer_vector<RT>]] by [[ivector]]. Also replacements in create are not
made at all. The first request is easily handled. I assumed that both sides of
the substitution consist of aphanumeric characters only (\verb+\w+). I changed
this to non-space. This still does not allow blanks in either side. So the
solution is not perfect. I discussed the matter with Michael and we agreed on
the following syntax. On either write -verb-S T- or \verb-S#T-. In the former
case S and T are not allowed to contain blanks.
\item he wants me to remove all temporary files.
\end{itemize}
I performed all three changes.
\item August 2nd, 96: I noticed that paremeter lists look strange if one of the
types is templeted, e.g., [[edge_array<edge>]] rev will have no blank between
[[>]] and [[rev]]. I made one change in [[M_convert]]. When it treats template
brackets I insert a space after a [[>]]. This change handles parameter lists
correctly but not quoted code.
\item August 20th, 96: I introduced the command Menum for the definition of
enumeration types. I want the layout enum Typename(in roman) { list of
alternatives in typewriter } text of body of enum.
\item September 15th, 96: Michael suggested two changes, this one and the next.
[[> >]] in return type is treated incorrectly. I made two changes. When type
is parsed I remove only beginning and trailing blanks but not interior blanks.
[[convert_M]] uses a more refined strategy to typeset template delimiters.
\item the warning uneven number of [[|]] is written into the tex-file and not
on standard output. I changed this by using both CERR and CSTANDOUT.
\item My correction for nested templates is incorrect. |stack<E> S|
removes the blank before S. I use the following heuristics. If a string
submitted to [[convert_M]] contains [[<]] and [[>]] then all occurrences
of such symbols are assumed to be template brackets. If it does not then
they are assumed to be less or greater symbols. In the latter cases I let
latex do the spacing. In the former case I keep the spacing in the input.
I do not forsee a situation where I want to do both. Because one can
always write something like [[$|stack<E> S| < 5$]] instead of 
[[|stack<E> S < 5|]]. And I guess there is no way that a string involving
template brackets and less than sign automatically.
\item [[const&]] removal does not always work. An example is sort in list,
namely [[sort( int (*cmp)(const E&, const E&))]]. The first pair is not removed.
The reason is that I insisted that the parameter starts with const. Together with
the fact that I parse the parameter list only partially, i.e., do not discover
that I deal with a nested parameter list this left the first const-ref pair
undiscovered. I had to change two lines in 
[[@<<producing the manual entry@>>]].
\item remove empty lines introduces lines starting with \% in code section. I
made a small change in emptyline.pl: A line containig nwendcode and nwbegincode
does not move me out of codemode.
\item Need a way to document private functions. Also need the possiblity to
have manual comments nicely typeset in the implementation part of documents.
This is solved. October 96
\item Need to produce html-type output. I talked to Joachim about the
problem. He will look into it. This is solved. October 96.
\item December 16th, 96. I forgot that a class can have more than one template
argument. I added one line to correct this mistake (in the handling of
code-unit). Now, I delete \verb-template *<[ ,\w]*> *-.
\item have added a feature to produce very several outfiles
\item changed the lauout of functions such that very long return types are
handeled correctly.

\item I added new formatting features for local typedefs in the class
scope. There is a new section [[\Mtypes]] which introduces locally defined
types. There are three commands which can be used there \verb-\Menum-,
\verb-\Mtypedef- and \verb-\Mtypemember-. The first can be used to document enum
types. The second documents a whole typedef as needed in traits classes and the
third only declares the target type.
\end{itemize}

\section{Plans for changes}
\begin{itemize}
\item [[Fman two_tuple]] gives no output since the 
h-file has a name different from the type name.
\item computewidths should store the old values. Then
restorewidths should restore them.
\end{itemize}
\end{document}
