#!/usr/bin/env perl
# Project: 	Documentation Tools
# Descr:	Latex -->  MAN-page (groff -man), HTML and TexInfo;
# Language:	PERL (>= 5.0)
# Author:	Dr. Jürgen Vollmer, Juergen.Vollmer@informatik-vollmer.de
# $Id: latex2man,v 1.156 2010/12/22 12:44:30 vollmer Exp $
#
# Copyright (C) 1998 Dr. Juergen Vollmer
#                    Viktoriastrasse 15, D-76133 Karlsruhe, Germany
#                    Juergen.Vollmer@informatik-vollmer.de
# License:
#   This program can be redistributed and/or modified under the terms
#   of the LaTeX Project Public License Distributed from CTAN
#   archives in directory macros/latex/base/lppl.txt; either
#   version 1 of the License, or any later version.
#
# If you find this software useful, please send me a postcard.

require 5.0004_03;

use Getopt::Std;

# use strict 'vars';

$CMD=`basename $0`; chop ($CMD);
$gen_date = `date`; chomp $gen_date;       # date when the output was generated

sub date2str;
$VERSION = "1.24";
$DATE    = date2str ('$Date: 2010/12/22 12:44:30 $' =~ m|(\d+/\d+/\d+)|);

$tmp = "/tmp/$CMD.$$";

##################################################################
# check option and arguments
##################################################################

getopts('o:t:c:VhMHTLC:D:a:'); # -D1: write each read line -D2: write each word

sub usage
{
print <<'END';
usage: latex2man [-t transfile] [-c cssfile] [-HTML] [-C name] [-h] [-V] infile outfile.
  A tool to translate UNIX manual pages written with LaTeX into a format
  understood by the UNIX man(1)-command.
  Reads infile, writes outfile.

  -t transfile:  Translation for user defined LaTeX macros.
  -c CSSfile:    If -H is given, add a link to the \`CSSfile\' and use those
                 CSS definitions.
  -M:            Produce output suitable for the man(1) command (default).
  -H:            Instead of producing output suitable for the man(1) command,
                 HTML code is produced (despite of the name of the command).
  -T:            Instead of producing output suitable for the man(1) command,
		 TEXINFO code is produced (despite of the name of the command).
  -L:            Output the LaTeX source. Useful in conjunctin with the -C
                 option.
  -C name:       Enable conditional text \`name\'.
                 To enable more than one conditional name use quotes:
                 -C 'name1 name2 ...'
                 The following names are defined automatically:
		    -H defines  HTML
                    -T defines  TEXI
		    -M defines  MAN
		    -L defines  LATEX
  -a char:       Is used only in conjunction with -T.
	         Background:
		   TEXINFO ignores all blanks before the first word on a
                   new line. In order to produce some additional space before
	           that word (using \SP) some character has to be printed
		   before the additional space. By default this is a . (dot).
		 The \`char' specifies an alternative for that first character.
                 Giving a blank (-a" ") supresses the indentation of a line.
                 Note: only for the first \SP of a series that char is printed.
  -h:            Help.
  -V:            Version.

  Copyright (C) 1998 Dr. Jürgen Vollmer, Viktoriastr. 15, D-76133 Karlsruhe
  email: Juergen.Vollmer@informatik-vollmer.de
  License:
    This program can be redistributed and/or modified under the terms
    of the LaTeX Project Public License Distributed from CTAN
    archives in directory macros/latex/base/lppl.txt; either
    version 1 of the License, or any later version.

  If you find this software useful, please send me a postcard from the place
  where you are living.
END
    print "  Version $VERSION, $DATE.\n";
    exit 1;
}

($opt_h)     && usage;
($opt_V)     && print "Version: $VERSION, $DATE\n";

# check command line arguments
$opt_cnt = 0;
$opt_cnt++ if ($opt_H);
$opt_cnt++ if ($opt_T);
$opt_cnt++ if ($opt_M);
$opt_cnt++ if ($opt_L);
if ($opt_cnt == 0) {
    # if no option -H, -T, -M, -L is given, -M is the default
    $opt_M = 1;
}
die "$CMD: you may give only one of the -H -T -M -L options\n" if ($opt_cnt > 1);

(@ARGV == 2) || die "$CMD: Expected two arguments: infile outfile. Try \`$CMD -h'.\n";

my %cond_name;
if ($opt_C) {
    my $name;
    foreach $name ((split (/\s/, $opt_C))) {
	$cond_name{$name} = 1;
    }
}
$cond_name{MAN}   = 1 if ($opt_M);
$cond_name{HTML}  = 1 if ($opt_H);
$cond_name{TEXI}  = 1 if ($opt_T);
$cond_name{LATEX} = 1 if ($opt_L);


$SrcFile  = $ARGV[0];
$DestFile = $ARGV[1];
open (SRC,  "<$SrcFile")  || die "$CMD: Can't open file \`$SrcFile' for reading.\n";
if ($opt_H || $opt_T) {
    # DestFile will be written in the postprocess
    open (DEST, ">$tmp")      || die "$CMD: Can't open file \`$tmp' for writing.\n";
} else {
    open (DEST, ">$DestFile") || die "$CMD: Can't open file \`$DestFile' for writing.\n";
}

########################################################################

# global variables

# $Prefix is used to construct procedure and variable names
if ($opt_M) {
    $Prefix  = "man";
}
if ($opt_H) {
    $Prefix  = "html";
}
if ($opt_T) {
    $Prefix  = "texi";
}

$texiCenterLine = 0; # true, only in TEXI-mode  if a line must be centered
$paragraph    = 0; # true, if the last output was a paragraph marker
$newline      = 0; # true, if the last output was a newline char

$first_word   = 1; # true, if the next word to be processed is the first
                   #       of a new paragraph or after a line break.

# handling of itemize/enumerate/description environments:
$list_nest    = 0; # counts nesting of itemize/enumerate/description envrionments
$cur_list[0]  = "";# array, indexed with list_nest, indicates kind of list:
                   # values are:  'enum' / 'descr' / 'item'
$item_nr[0]   = 0; # array, indexed with list_nest, counts the number of \item in the
                   # list
$manRS        = 0; # true, if for Man a .RS was given after a \item

$inside_verb  = 0;  # true, if inside a verbatim environment
$inside_table = 0; # true, if inside a table environment
$first_column = 0; # true, if this is the first column in a table row
$columns      = 0; # nr of columns in the current table
$enum_nr      = 0; # current number of an enumeration
$nesting      = 0; # count recursive calls of interpret_word
$section_cnt  = 0; # Index into $sections
#$sections[0]      # Array of all sections
#$section_kind     # Array of section kind (subsection/section)

# translation of LaTeX macros without, with one and with two arguments
$Macro   = \%{$Prefix . "Macro"};
$Macro1a = \%{$Prefix . "Macro1a"};
$Macro1b = \%{$Prefix . "Macro1b"};
$Macro2a = \%{$Prefix . "Macro2a"};
$Macro2b = \%{$Prefix . "Macro2b"};
$Macro2c = \%{$Prefix . "Macro2c"};

# translations of special characters
$LetterCode = \%{$Prefix . "LetterCode"};

########################################################################

sub interpret_word;
sub interpret_line;
sub Print;
sub PrintM;
sub NL;

########################################################################
# Translation for LaTeX macros for MAN

# translation of special characters
$manLetterCode{'ä'} = 'ä';
$manLetterCode{'ö'} = 'ö';
$manLetterCode{'ü'} = 'ü';
$manLetterCode{'Ä'} = 'Ä';
$manLetterCode{'Ö'} = 'Ö';
$manLetterCode{'Ü'} = 'Ü';
$manLetterCode{'ß'} = 'ß';

# LaTeX macros without arguments
$manMacro{'LaTeX'} 	= 'LaTeX';
$manMacro{'LATEX'} 	= 'LaTeX';     # needed, since \LaTeX is contained in a
                                       # section name (which are transposed
				       # into uppercase
$manMacro{'itemsep'}    = ' ';

# some math
$manMacro{'rightarrow'} = '-->';
$manMacro{'Rightarrow'} = '==>';
$manMacro{'leftarrow'}  = '<--';
$manMacro{'Leftarrow'}  = '<==';
$manMacro{'ge'}         = '>=';
$manMacro{'le'}         = '<=';

$manMacro{'Dollar'}     = '$';
$manMacro{'Bar'} 	= '|';
$manMacro{'Bs'} 	= '\\\\';
$manMacro{'Tilde'} 	= '~';
$manMacro{'hline'} 	= '\n_';
$manMacro{'noindent'} 	= '';
$manMacro{'copyright'} 	= '(C)';
$manMacro{'Dots'} 	= '\&...\n';
$manMacro{'Circum'} 	= '^';
$manMacro{'Lbr'} 	= '[';
$manMacro{'Rbr'} 	= ']';
$manMacro{'LBr'} 	= '{';
$manMacro{'RBr'} 	= '}';
$manMacro{'Percent'} 	= '%';
$manMacro{'Bullet'}     = '*';
$manMacro{'TEXbr'}	= '';
$manMacro{'MANbr'}	= '\n.br\n';
$manMacro{'TEXIbr'}	= '';
$manMacro{'HTMLbr'}	= '';
$manMacro{'medskip'}	= '\n';
$manMacro{'SP'}         = '\fB \fP';  # hack hack this works even on
				      # the beginning of a line
$manMacro{'SPfirst'}    = $manMacro{'SP'};

$manMacro{'~'}		= ' ';
$manMacro{'|'}		= '|';
$manMacro{'<'}		= '<';
$manMacro{'>'}		= '>';
$manMacro{'<='}		= '<=';
$manMacro{'>='}		= '>=';
$manMacro{'='}		= '=';
$manMacro{'<>'}		= '<>';
$manMacro{'{'}		= '{';
$manMacro{'}'}		= '}';
$manMacro{'_'}		= '_';
$manMacro{'$'}		= '$';
$manMacro{'#'}		= '#';
$manMacro{'&'}		= '&';
$manMacro{'%'}		= '%';
$manMacro{'-'}		= '';
$manMacro{','}		= ' ';

$manMacro{'\\'}		= '\n.br';	# line break
$manMacro{'\\Tab'}	= '\nT}';       # end of column in a table environment

# LaTeX macros with one argument
$manMacro1a{'emph'} 	 	= '\fI';
	$manMacro1b{'emph'} 	= '\fP';
$manMacro1a{'textbf'} 	 	= '\fB';
	$manMacro1b{'textbf'} 	= '\fP';
$manMacro1a{'texttt'} 	 	= '';
	$manMacro1b{'texttt'} 	= '';
$manMacro1a{'verb'} 	 	= '';
	$manMacro1b{'verb'} 	= '';
$manMacro1a{'underline'} 	= '\n.ul\n';
	$manMacro1b{'underline'}= '\n';
$manMacro1a{'section'}   	= '\n.SH ';
	$manMacro1b{'section'}  = '\n';
$manMacro1a{'subsection'}	= '\n.SS ';
	$manMacro1b{'subsection'} = '';
$manMacro1a{'subsubsection'}	= '\n.SS ';
	$manMacro1b{'subsubsection'} = '';

$manMacro1a{'Prog'} 	 	= '';
	$manMacro1b{'Prog'} 	= '';
$manMacro1a{'File'} 	 	= '';
	$manMacro1b{'File'} 	= '';
$manMacro1a{'Opt'} 	 	= '\fB';
	$manMacro1b{'Opt'} 	= '\fP';
$manMacro1a{'oOpt'} 	 	= '[\fB';
	$manMacro1b{'oOpt'} 	= '\fP]';
$manMacro1a{'Arg'} 	 	= '\fI';
	$manMacro1b{'Arg'} 	= '\fP';
$manMacro1a{'oArg'} 	 	= '[\fI';
	$manMacro1b{'oArg'} 	= '\fP]';
$manMacro1a{'Email'}		= '\fB';
	$manMacro1b{'Email'}	= '\fP';
$manMacro1a{'URL'}		= '\fB';
	$manMacro1b{'URL'}	= '\fP';

# LaTeX macros with two arguments
$manMacro2a{'Cmd'} 		= '\fI';
	$manMacro2b{'Cmd'} 	= '\fP(';
	$manMacro2c{'Cmd'} 	= ')';
$manMacro2a{'OptArg'} 		= '\fB';
	$manMacro2b{'OptArg'} 	= '\fP\fI';
	$manMacro2c{'OptArg'} 	= '\fP';
$manMacro2a{'OptoArg'} 		= '\fB';
	$manMacro2b{'OptoArg'} 	= '\fP[\fI';
	$manMacro2c{'OptoArg'} 	= '\fP]';
$manMacro2a{'oOptArg'} 		= '[\fB';
	$manMacro2b{'oOptArg'} 	= '\fP\fI';
	$manMacro2c{'oOptArg'} 	= '\fP]';
$manMacro2a{'oOptoArg'} 	= '[\fB';
	$manMacro2b{'oOptoArg'}	= '\fP[\fI';
	$manMacro2c{'oOptoArg'}	= '\fP]]';
$manMacro2a{'setlength'}	= '';
	$manMacro2b{'setlength'}= '';
	$manMacro2c{'setlength'}= '';

########################################################################
# Translation for LaTeX macros for HTML

# translation of special characters
$htmlLetterCode{'ä'} = '&auml;';
$htmlLetterCode{'ö'} = '&ouml;';
$htmlLetterCode{'ü'} = '&uuml;';
$htmlLetterCode{'Ä'} = '&Auml;';
$htmlLetterCode{'Ö'} = '&Ouml;';
$htmlLetterCode{'Ü'} = '&Uuml;';
$htmlLetterCode{'ß'} = '&szlig;';

# LaTeX macros without arguments
$htmlMacro{'LaTeX'} 	= 'LaTeX';
$htmlMacro{'LATEX'} 	= 'LaTeX';     # needed, since \LaTeX is contained in a
                                       # section name (which are transposed
				       # into uppercase
$htmlMacro{'itemsep'}   = '';

# some math
$htmlMacro{'rightarrow'} = '--&gt;';
$htmlMacro{'Rightarrow'} = '==&gt;';
$htmlMacro{'leftarrow'}  = '&lt;--';
$htmlMacro{'Leftarrow'}  = '&lt;==';
$htmlMacro{'ge'}         = '&gt;';
$htmlMacro{'le'}         = '&lt;=';

$htmlMacro{'Dollar'}    = '$';
$htmlMacro{'Bar'} 	= '|';
$htmlMacro{'Bs'} 	= '\\';
$htmlMacro{'Tilde'} 	= '~';
$htmlMacro{'hline'} 	= '';
$htmlMacro{'noindent'} 	= '';
$htmlMacro{'copyright'} = '&copy;';
$htmlMacro{'Dots'} 	= '...';
$htmlMacro{'Circum'} 	= '^';
$htmlMacro{'Lbr'} 	= '[';
$htmlMacro{'Rbr'} 	= ']';
$htmlMacro{'LBr'} 	= '{';
$htmlMacro{'RBr'} 	= '}';
$htmlMacro{'Percent'} 	= '%';
$htmlMacro{'Bullet'}    = '*';
$htmlMacro{'TEXbr'}	= '';
$htmlMacro{'MANbr'}	= '';
$htmlMacro{'TEXIbr'}	= '';
$htmlMacro{'HTMLbr'}	= '<br>\n';
$htmlMacro{'medskip'}	= '<br>\n';
$htmlMacro{'SP'}	= '&nbsp;&nbsp;';
$htmlMacro{'SPfirst'}    = $htmlMacro{'SP'};

$htmlMacro{'~'}		= '&nbsp;';
$htmlMacro{'|'}		= '|';
$htmlMacro{'<'}		= '&lt;';
$htmlMacro{'>'}		= '&gt;';
$htmlMacro{'<='}	= '&lt;=';
$htmlMacro{'>='}	= '&gt;=';
$htmlMacro{'='}		= '=';
$htmlMacro{'<>'}	= '&lt;&gt;';
$htmlMacro{'{'}		= '{';
$htmlMacro{'}'}		= '}';
$htmlMacro{'_'}		= '_';
$htmlMacro{'$'}		= '$';
$htmlMacro{'#'}		= '#';
$htmlMacro{'&'}		= '&amp;';
$htmlMacro{'%'}		= '%';
$htmlMacro{'-'}		= '';
$htmlMacro{','}		= ' ';

$htmlMacro{'\\'}	= '<br>\n';		# line break
$htmlMacro{'\\Tab'}	= '</td>\n</tr>\n';	# end of column in a table environment

# LaTeX macros with one argument
$htmlMacro1a{'emph'} 		= '<em>';
	$htmlMacro1b{'emph'} 	= '</em>';
$htmlMacro1a{'textbf'} 		= '<strong>';
	$htmlMacro1b{'textbf'} 	= '</strong>';
$htmlMacro1a{'texttt'} 		= '<tt>';
	$htmlMacro1b{'texttt'} 	= '</tt>';
$htmlMacro1a{'verb'} 		= '<tt>';
	$htmlMacro1b{'verb'} 	= '</tt>';
$htmlMacro1a{'underline'} 	= '<u>';
	$htmlMacro1b{'underline'}  = '</u>';
  $htmlMacro1a{'section'}   	= '\n<h2>';
	  $htmlMacro1b{'section'} = '</h2>\n';
  $htmlMacro1a{'subsection'}	= '\n<h4>';
	  $htmlMacro1b{'subsection'} = '</h4>\n';
  $htmlMacro1a{'subsubsection'}	= '\n<h5>';
	  $htmlMacro1b{'subsubsection'} = '</h5>\n';
if ($opt_c) {
  # use CSS
  # thanks to Tom Brand <tbrand@manumit-systems.com>
  $htmlMacro1a{'Email'}		= '\n<font class="emailstyle">';
	  $htmlMacro1b{'Email'}	= '</font>';
  $htmlMacro1a{'URL'}		= '\n<font class="urlstyle">';
	  $htmlMacro1b{'URL'}	= '</font>';

  $htmlMacro1a{'Prog'} 		= '<font class="progname">';
	  $htmlMacro1b{'Prog'} 	= '</font>';
  $htmlMacro1a{'File'} 		= '<font class="filename">';
	  $htmlMacro1b{'File'} 	= '</font>';
  $htmlMacro1a{'Opt'} 		= '<font class="optstyle">';
	  $htmlMacro1b{'Opt'} 	= '</font>';
  $htmlMacro1a{'oOpt'} 		= '[<font class="optstyle">';
	  $htmlMacro1b{'oOpt'} 	= '</font>]';
  $htmlMacro1a{'Arg'} 		= '<font class="argstyle">';
	  $htmlMacro1b{'Arg'} 	= '</font>';
  $htmlMacro1a{'oArg'} 		= '[<font class="argstyle">';
	  $htmlMacro1b{'oArg'}    = '</font>]';
} else {
  # don't use CSS
  $htmlMacro1a{'Email'}		= '\n<tt>';
	  $htmlMacro1b{'Email'}	= '</tt>';
  $htmlMacro1a{'URL'}		= '\n<tt>';
	  $htmlMacro1b{'URL'}	= '</tt>';

  $htmlMacro1a{'Prog'} 		= '<tt>';
	  $htmlMacro1b{'Prog'} 	= '</tt>';
  $htmlMacro1a{'File'} 		= '<tt>';
	  $htmlMacro1b{'File'} 	= '</tt>';
  $htmlMacro1a{'Opt'} 		= '<b>';
	  $htmlMacro1b{'Opt'} 	= '</b>';
  $htmlMacro1a{'oOpt'} 		= '[<b>';
	  $htmlMacro1b{'oOpt'} 	= '</b>]';
  $htmlMacro1a{'Arg'} 		= '<i>';
	  $htmlMacro1b{'Arg'} 	= '</i>';
  $htmlMacro1a{'oArg'} 		= '[<i>';
	  $htmlMacro1b{'oArg'}    = '</i>]';
}

# LaTeX macros with two arguments
if (opt_c) {
  $htmlMacro2a{'Cmd'} 		  = '<font class="commandname">';
	  $htmlMacro2b{'Cmd'} 	  = '</font>(';
	  $htmlMacro2c{'Cmd'} 	  = ')';
  $htmlMacro2a{'OptArg'} 		  = '<font class="optstyle">';
	  $htmlMacro2b{'OptArg'} 	  = '</font><font class="argstyle">';
	  $htmlMacro2c{'OptArg'} 	  = '</font>';
  $htmlMacro2a{'OptoArg'} 	  = '<font class="optstyle">';
	  $htmlMacro2b{'OptoArg'}	  = '</font>[<font class="argstyle">';
	  $htmlMacro2c{'OptoArg'}	  = '</font>]';
  $htmlMacro2a{'oOptArg'} 	  = '[<font class="optstyle">';
	  $htmlMacro2b{'oOptArg'}   = '</font><font class="argstyle">';
	  $htmlMacro2c{'oOptArg'}   = '</font>]';
  $htmlMacro2a{'oOptoArg'} 	  = '[<font class="optstyle">';
	  $htmlMacro2b{'oOptoArg'}  = '</font>[<font class="argstyle">';
	  $htmlMacro2c{'oOptoArg'}  = '</font>]]';
} else {
  $htmlMacro2a{'Cmd'} 		  = '<em>';
	  $htmlMacro2b{'Cmd'} 	  = '</em>(';
	  $htmlMacro2c{'Cmd'} 	  = ')';
  $htmlMacro2a{'OptArg'} 		  = '<b>';
	  $htmlMacro2b{'OptArg'} 	  = '</b><i>';
	  $htmlMacro2c{'OptArg'} 	  = '</i>';
  $htmlMacro2a{'OptoArg'} 	  = '<b>';
	  $htmlMacro2b{'OptoArg'}	  = '</b>[<i>';
	  $htmlMacro2c{'OptoArg'}	  = '</i>]';
  $htmlMacro2a{'oOptArg'} 	  = '[<b>';
	  $htmlMacro2b{'oOptArg'}   = '</b><i>';
	  $htmlMacro2c{'oOptArg'}   = '</i>]';
  $htmlMacro2a{'oOptoArg'} 	  = '[<b>';
	  $htmlMacro2b{'oOptoArg'}  = '</b>[<i>';
	  $htmlMacro2c{'oOptoArg'}  = '</i>]]';
}
$htmlMacro2a{'setlength'}	  = '';
	$htmlMacro2b{'setlength'} = '';
	$htmlMacro2c{'setlength'} = '';

# we handle sections in HTML as having two arguments, 1. the number, 2. the name
if ($opt_c) {
  # use CSS
  # thanks to Tom Brand <tbrand@manumit-systems.com>
  $htmlMacro2a{'section'}   	   = '\n<h2 class="sectionname"><a name="section_';
	  $htmlMacro2b{'section'}    = '">';
	  $htmlMacro2c{'section'}    = '</a></h2>\n';
  $htmlMacro2a{'subsection'}   	   = '\n<h4 class="subsectionname"><a name="section_';
	  $htmlMacro2b{'subsection'} = '">';
	  $htmlMacro2c{'subsection'} = '</a></h4>\n';
  $htmlMacro2a{'subsubsection'}         = '\n<h5 class="subsubsectionname"><a name="section_';
	  $htmlMacro2b{'subsubsection'} = '">';
	  $htmlMacro2c{'subsubsection'} = '</a></h5>\n';

  # we handle Email and URL special in HTML, the LaTeX argument is doubled.
  $htmlMacro2a{'Email'}		= '<a class="emailstyle" href ="mailto:';
	  $htmlMacro2b{'Email'}	= '">';
	  $htmlMacro2c{'Email'}	= '</a>';
  $htmlMacro2a{'URL'}		= '<a class="urlstyle" href ="';
	  $htmlMacro2b{'URL'}	= '"><tt>';
	  $htmlMacro2c{'URL'}	= '</tt></a>';

}else{
  # don't use CSS
  $htmlMacro2a{'section'}   	   = '\n<h2><a name="section_';
	  $htmlMacro2b{'section'}    = '">';
	  $htmlMacro2c{'section'}    = '</a></h2>\n';
  $htmlMacro2a{'subsection'}   	   = '\n<h4><a name="section_';
	  $htmlMacro2b{'subsection'} = '">';
	  $htmlMacro2c{'subsection'} = '</a></h4>\n';
  $htmlMacro2a{'subsubsection'}         = '\n<h5><a name="section_';
	  $htmlMacro2b{'subsubsection'} = '">';
	  $htmlMacro2c{'subsubsection'} = '</a></h5>\n';

  # we handle Email and URL special in HTML, the LaTeX argument is doubled.
  $htmlMacro2a{'Email'}		= '<a href ="mailto:';
	  $htmlMacro2b{'Email'}	= '"><tt>';
	  $htmlMacro2c{'Email'}	= '</tt></a>';
  $htmlMacro2a{'URL'}		= '<a href ="';
	  $htmlMacro2b{'URL'}	= '"><tt>';
	  $htmlMacro2c{'URL'}	= '</tt></a>';
}

########################################################################
# Translation for LaTeX macros for TexInfo

# translation of special characters
$texiLetterCode{'ä'} = '@"a';
$texiLetterCode{'ö'} = '@"o';
$texiLetterCode{'ü'} = '@"u';
$texiLetterCode{'Ä'} = '@"A';
$texiLetterCode{'Ö'} = '@"O';
$texiLetterCode{'Ü'} = '@"U';
$texiLetterCode{'ß'} = '@ss{}';

# LaTeX macros without arguments
$texiMacro{'LaTeX'} 	 = 'LaTeX';
$texiMacro{'LATEX'} 	 = 'LaTeX';    # needed, since \LaTeX is contained in a
                                       # section name (which are transposed
				       # into uppercase
$texiMacro{'itemsep'}    = '';

# some math
$texiMacro{'rightarrow'} = '-->';
$texiMacro{'Rightarrow'} = '==>';
$texiMacro{'leftarrow'}  = '<--';
$texiMacro{'Leftarrow'}  = '<==';
$texiMacro{'ge'}         = '>=';
$texiMacro{'le'}         = '<=';

$texiMacro{'Dollar'}    = '$';
$texiMacro{'Bar'} 	= '|';
$texiMacro{'Bs'} 	= '\\';
$texiMacro{'Tilde'} 	= '~';
$texiMacro{'hline'} 	= '';
$texiMacro{'noindent'} 	= '\n@noindent\n';
$texiMacro{'copyright'} = '@copyright{}';
$texiMacro{'Dots'} 	= '...';
$texiMacro{'Circum'} 	= '^';
$texiMacro{'Lbr'} 	= '[';
$texiMacro{'Rbr'} 	= ']';
$texiMacro{'LBr'} 	= '@{';
$texiMacro{'RBr'} 	= '@}';
$texiMacro{'Percent'} 	= '%';
$texiMacro{'Bullet'}    = '*';
$texiMacro{'TEXbr'}	= '';
$texiMacro{'MANbr'}	= '';
$texiMacro{'TEXIbr'}	= '@*\n';
$texiMacro{'HTMLbr'}	= '';
$texiMacro{'medskip'}	= '@sp 2\n';
$texiMacro{'SP'}	= '@ @ ';

if ($opt_a) {
  $texiMacro{'SPfirst'} = $opt_a . '@ ';
 } else {
  $texiMacro{'SPfirst'} = '.@ ';
}

$texiMacro{'~'}		= ' ';
$texiMacro{'|'}		= '|';
$texiMacro{'<'}		= '<';
$texiMacro{'>'}		= '>';
$texiMacro{'<='}	= '<=';
$texiMacro{'>='}	= '>=';
$texiMacro{'='}		= '=';
$texiMacro{'<>'}	= '<>';
$texiMacro{'{'}		= '@{';
$texiMacro{'}'}		= '@}';
$texiMacro{'_'}		= '_';
$texiMacro{'$'}		= '$';
$texiMacro{'#'}		= '#';
$texiMacro{'&'}		= '&';
$texiMacro{'%'}		= '%';
$texiMacro{'-'}		= '@-';
$texiMacro{','}		= ' ';

$texiMacro{'\\'}	= '@*\n';	# line break
$texiMacro{'\\Tab'}	= '\n';		# end of column in a table environment

# LaTeX macros with one argument
$texiMacro1a{'emph'} 		= '@emph{';	$texiMacro1b{'emph'} 	   = '}';
$texiMacro1a{'textbf'} 		= '@strong{';	$texiMacro1b{'textbf'} 	   = '}';
$texiMacro1a{'texttt'} 		= '@t{';	$texiMacro1b{'texttt'} 	   = '}';
$texiMacro1a{'verb'} 		= '@t{';	$texiMacro1b{'verb'} 	   = '}';
$texiMacro1a{'underline'} 	= '';		$texiMacro1b{'underline'}  = '';
$texiMacro1a{'section'}   	= '\n@section ';    $texiMacro1b{'section'}    = '\n';
$texiMacro1a{'subsection'}	= '\n@subsection '; $texiMacro1b{'subsection'} = '\n';
$texiMacro1a{'subsubsection'}	= '\n@subsubsection '; $texiMacro1b{'subsubsection'} = '\n';

$texiMacro1a{'Prog'} 		= '';		$texiMacro1b{'Prog'} 	   = '';
$texiMacro1a{'File'} 		= '@file{';	$texiMacro1b{'File'} 	   = '}';
$texiMacro1a{'Opt'} 		= '';		$texiMacro1b{'Opt'} 	   = '';
$texiMacro1a{'oOpt'} 		= '[ ';		$texiMacro1b{'oOpt'} 	   = ' ]';
$texiMacro1a{'Arg'} 		= '@var{';	$texiMacro1b{'Arg'} 	   = '}';
$texiMacro1a{'oArg'} 		= '[ @var{';	$texiMacro1b{'oArg'} 	   = '} ]';
$texiMacro1a{'Email'}		= '@email{';    $texiMacro1b{'Email'}	  = '}';
$texiMacro1a{'URL'}		= '@url{';      $texiMacro1b{'URL'}	  = '}';

# LaTeX macros with two arguments
$texiMacro2a{'Cmd'} 		  = '';
	$texiMacro2b{'Cmd'} 	  = '(';
	$texiMacro2c{'Cmd'} 	  = ')';
$texiMacro2a{'OptArg'} 		  = '';
	$texiMacro2b{'OptArg'} 	  = '@var{';
	$texiMacro2c{'OptArg'} 	  = '}';
$texiMacro2a{'OptoArg'} 	  = '';
	$texiMacro2b{'OptoArg'}   = '[@var{';
	$texiMacro2c{'OptoArg'}   = '}]';
$texiMacro2a{'oOptArg'} 	  = '[ ';
	$texiMacro2b{'oOptArg'}   = '@var{';
	$texiMacro2c{'oOptArg'}   = '} ]';
$texiMacro2a{'oOptoArg'} 	  = '[ ';
	$texiMacro2b{'oOptoArg'}  = '[@var{';
	$texiMacro2c{'oOptoArg'}  = '}] ]';
$texiMacro2a{'setlength'}	  = '';
	$texiMacro2b{'setlength'} = '';
	$texiMacro2c{'setlength'} = '';

########################################################################
# reading of translations for user macros

if ($opt_t) {
    do $opt_t;
}

########################################################################
# processing for MAN

sub manStart
{
    printf DEST "\'\\\" t\n";   # process with tbl
    printf DEST ".\\\" Manual page created with $CMD on $gen_date\n";
    printf DEST ".\\\" NOTE: This file is generated, DO NOT EDIT.\n";

    # Definitionen von Verbatimbegin and Verbatimend
    Print ".de Vb\n.ft CW\n.nf\n..\n.de Ve\n.ft R\n\n.fi\n..\n";

    Print ".TH \"$Name\" \"$chapter\" \"". $date ."\" \"";
    interpret_word "$tool";
    Print "\" \""; interpret_word "$tool"; Print "\""; NL;
    # thanks to Andrew Anderson <aja@emulab.ee.mu.oz.au>
}
sub manEnd
{
    NL; printf DEST ".\\\" NOTE: This file is generated, DO NOT EDIT.\n";
}
sub manSection
{
    my ($cnt, $kind, $section) = @_;
    if ($kind ne "subsubsection"){
       $section = uc $section;
    }
    interpret_line "\\$kind\{$section\}";
}
sub manParagraph
{
    if (!$paragraph) {
	if ($manRS == 0 && $list_nest > 1) {
	    Print '\n.RS';
	    $manRS = 1;
	}
	Print '\n.PP\n';
	$paragraph  = 1;
    }
}
sub manVerb
{
    my $arg = $_[0];
    if ($arg =~ /^\./) { print DEST '\\&' };
    Print $arg
}
sub manItemWithArg
{
    my $arg = $_[0];
    if ($manRS == 1) {
	Print '\n.RE\n';
    }
    $manRS      = 0;
    Print '\n.TP\n';
    interpret_word $arg;
    PrintM ' ';
    NL;
}
sub manItem
{
    if ($manRS == 1) {
	Print '\n.RE\n';
    }
    $manRS      = 0;
    Print '\n.TP\n';
    if ($cur_list[$list_nest] eq 'item') {
	Print '.B *';
    } elsif ($cur_list[$list_nest] eq 'enum') {
	Print $item_nr[$list_nest] . '.';
    }
    NL;
}
sub manDescriptionStart
{
    if ($list_nest > 1) {
	Print '\n.RS\n';
    }
}
sub manDescriptionEnd
{
    if ($manRS) {
	Print '\n.RE\n';
	$manRS == 0;
    }
    if ($list_nest > 1) {
	Print '\n.RE\n';
    }
    manParagraph;
}
sub manItemStart
{
    if ($list_nest > 1) {
	Print '\n.RS\n';
    }
}
sub manItemEnd
{
    if ($manRS) {
	Print '\n.RE\n';
	$manRS == 0;
    }
    if ($list_nest > 1) {
	Print '\n.RE\n';
    }
    manParagraph;
}
sub manEnumEnd
{
    if ($manRS) {
	Print '\n.RE\n';
	$manRS == 0;
    }
    if ($list_nest > 1) {
	Print '\n.RE\n';
    }
    manParagraph;
}

sub manEnumStart
{
    if ($list_nest > 1) {
	Print '\n.RS\n';
    }
}
sub manCenterStart
{
    PrintM '\n.ce 100\n';
}
sub manCenterEnd
{
    PrintM '\n.ce 0\n';
}
sub manNameStart
{
    interpret_line "\\section\{NAME\}$rest";
}
sub manNameEnd
{
    # nothing
}
sub manTableStart
{
    my $columns = $_[0];
    my $width   = $_[1];
    my $i;
    manParagraph;
    Print '.TS\n';
    Print 'tab(&);\n';
    for ($i = 1; $i <= $columns; $i++) {
	Print " l";
    }
    Print "w($width)" if ($width);
    Print '.\n';
}
sub manTableSep
{
    Print '\nT}&T{\n';
}
sub manTableEnd
{
    Print '\n.TE\n';
    manParagraph;
}

sub manVerbatimStart
{
    Print '\n.Vb\n';
}

sub manVerbatimEnd
{
    Print '.Ve\n';
}

sub manVerbatimLine
{
  s/\\/\\\\/g;
  s/-/\\-/g;
  print DEST "$_";
}

###########################################################################
# processing for HTML

sub htmlStart
{
    Print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">"; 	NL;
    Print "<!-- Manual page created with $CMD on $gen_date"; 		NL;
    Print "  ** Author of $CMD: Juergen.Vollmer\@informatik-vollmer.de";NL;
    Print "  ** NOTE: This file is generated, DO NOT EDIT. -->"; 	NL;
    Print "<html>";							NL;
    Print "<head><title>$Name</title>"; 				NL;

  if ($opt_c) {
    Print '<link href="'.$opt_c.'" rel="stylesheet" type="text/css">';  NL;
    Print "</head><body>"; 						NL;
    Print '<h1 class="titlehead">';	                                NL;
    interpret_line $title;
    Print '</h1>'; 							NL;
    Print '<h4 class="authorhead">'; interpret_word $author; Print '</h4>'; NL;
    Print "<h4 class=\"datehead\">$date</h4>"; 				    NL;
    Print "<h4 class=\"versionhead\">Version $version</h4>"; 		    NL;
  } else {
    Print "</head><body bgcolor=\"white\">"; 					NL;

    Print "<h1 align=center>"; NL;
    interpret_line $title;
    Print "</h1>"; 							NL;
    Print "<h4 align=center>"; interpret_word $author; Print "</h4>"; 	NL;
    Print "<h4 align=center>$date</h4>"; 				NL;
    Print "<h4 align=center>Version $version</h4>"; 			NL;
  }
}
sub htmlEnd
{
    Print "</body>"; 						 NL;
    Print "</html>"; 						 NL;
    Print "<!-- NOTE: This file is generated, DO NOT EDIT. -->"; NL;
}
sub htmlSection
{
    my ($cnt, $kind, $section) = @_;
    interpret_line "\\$kind\{$cnt\}\{$section\}";
}
sub htmlCenterStart
{
    Print '\n<div align=center>\n';
}
sub htmlCenterEnd
{
    Print '\n</div>\n';
}
sub htmlNameStart
{
    # nothing
}
sub htmlNameEnd
{
    Print '\n@@INSERTION-POINT@@-TOC@@\n';
}
sub htmlParagraph
{
    if (!$paragraph) {
	NL; Print "<p>"; NL;
	$paragraph = 1;
    }
}
sub htmlVerb
{
    $arg = $_[0];
    $arg =~ s/&/&amp;/g;
    $arg =~ s/>/&gt;/g;
    $arg =~ s/</&lt;/g;
    Print $arg;
}
sub htmlItemWithArg
{
    my $arg = $_[0];
    NL;
    if ($item_nr[$list_nest] > 1) {
	NL; Print "</dd>"; NL;
    }
    Print "<dt>";
    interpret_word $arg; Print "</dt>"; NL;
    Print "<dd>";
}
sub htmlItem
{
    if ($item_nr[$list_nest] > 1) {
	Print '</li>\n';
    }
    if ($cur_list[$list_nest] eq 'item') {
	Print '<li>';
    } elsif ($cur_list[$list_nest] eq 'enum') {
	Print '<li value =' . $item_nr[$list_nest] .'>';
    }
}
sub htmlDescriptionStart
{
    NL; Print "<dl compact>"; NL;
}
sub htmlDescriptionEnd
{
    NL; Print "</dd>\n</dl>"; NL;
}
sub htmlItemStart
{
    NL; Print "<ul compact>"; NL;
}
sub htmlItemEnd
{
    NL; Print "</li>\n</ul>"; NL;
}
sub htmlEnumStart
{
    NL; Print "<ol compact>"; NL;
}
sub htmlEnumEnd
{
    NL; Print "</li>\n</ol>"; NL;
}
sub htmlTableStart
{
    my $columns = $_[0];
    my $width   = $_[1];
    NL;
    if ($opt_c) {
	Print '<table summary="table" class="tablestyle">';
    } else{
	Print '<table summary="table">';
    }
    NL;
}
sub htmlTableSep
{
    if ($first_column == 0) {
	Print '</td>\n';
    }
    if ($opt_c) {
	Print '<td class="cellstyle">';
    } else {
	Print '<td>';
    }
}
sub htmlTableEnd
{
    NL; Print "</table>"; NL;
}

sub htmlVerbatimStart
{
    NL; Print '<pre>'; NL;
}

sub htmlVerbatimEnd
{
    Print '</pre>'; NL;
}

sub htmlVerbatimLine
{
  s/&/&amp;/g;
  s/</&lt;/g;
  s/>/&gt;/g;
  print DEST "$_";
}

###########################################################################
# processing for TexInfo

sub texiStart
{
    Print '\input texinfo   @c -*-texinfo-*-'; 			NL;
    Print '@c %**start of header';				NL;
    Print '@setfilename ' . "$name.info";			NL;
    Print '@settitle ' . "$name";				NL;
    Print '@c %**end of header';				NL;
    Print '@c Manual page created with' ." $CMD on $gen_date>";	NL;
    Print '@c NOTE: This file is generated, DO NOT EDIT.'; 	NL;
}
sub texiEnd
{
    Print '@bye'; 						NL;
    Print '@c NOTE: This file is generated, DO NOT EDIT.'; 	NL;
}
sub texiSection
{
    my ($cnt, $kind, $section) = @_;
    if (uc $sections[$cnt-1] eq "SYNOPSIS") {
	Print '\n@@INSERTION-POINT@@-TOC@@\n';
	$sections[$cnt-1] = "Top";   # The predecessor node is Top and not SYNOPSIS
    }
    if (uc $sections[$cnt] eq "SYNOPSIS") {
	$cnt == 1 ||
	    die "$CMD: The Synopsis section must be the first section after\n" .
		"\t the Name environment\n";
    } else {
	Print '\n@@INSERTION-POINT@@-TEXI-SEC@@' . " $kind $cnt" . '\n';
    }
    interpret_line "\\$kind\{$section\}";
}
sub texiNameStart
{
    my ($name, $chapter, $author, $tool) = @_;
    $sections[0] = "Top";
    # Print '@dircategory ' .$tool;				NL;
    Print '@dircategory Man-pages';				NL;
    Print '@direntry';						NL;
    Print "* " . (ucfirst $name) . ": ($name). Its Man-Page ";	NL;
    Print '@end direntry';					NL;
    Print '@titlepage';						NL;
    Print '@title ' . "$name";					NL;
    Print '@subtitle ' . "$tool";				NL;
    Print '@author ' . "$author";				NL;
    Print '@end titlepage';					NL;
    Print '\n@@INSERTION-POINT@@-TEXI-TOP@@';			NL;
    Print '@top ' . "$name";					NL;
}
sub texiNameEnd
{
    # nothing
}
sub texiParagraph
{
    if (!$paragraph) {
	NL; print DEST "\n";
	$paragraph = 1;
    }
}
sub texiVerb
{
    $arg = $_[0];
    $arg =~ s/({|})/\@$1/g;
    Print $arg;
}
sub texiItemWithArg
{
    my $arg = $_[0];
    Print '\n@item ';
    interpret_word $arg;
    NL;
}
sub texiItem
{
    Print '\n@item\n';
}
sub texiDescriptionStart
{
    Print '\n@table @samp\n';
}
sub texiDescriptionEnd
{
    Print '\n@end table\n';
}
sub texiItemStart
{
    Print '\n@itemize @bullet\n';
}
sub texiItemEnd
{
    Print '\n@end itemize\n';
}
sub texiCenterStart
{
    $texiCenterLine      = 1;
    $newline             = 0;
    $texiMacro{'\\'}     = '@*'; # line break
    $texiMacro{'TEXIbr'} = '@*';
    NL;
}
sub texiCenterEnd
{
    $texiCenterLine      = 0;
    $newline             = 0;
    $texiMacro{'\\'}     = '@*\n';	# line break
    $texiMacro{'TEXIbr'} = '@*\n';
    NL;
}

sub texiEnumStart
{
    Print '\n@enumerate\n';
}
sub texiEnumEnd
{
    Print '\n@end enumerate\n';
}
sub texiTableStart
{
    my $columns = $_[0];
    my $width   = $_[1];
    my $i;
    Print '\n@multitable @columnfractions ';
    for ($i = 1; $i <= $columns; $i++) {
	Print " " .0.9/$columns ;
    }
    Print '\n';
}
sub texiTableSep
{
    Print '@tab ';
}
sub texiTableEnd
{
    Print '\n@end multitable\n';
}

sub texiVerbatimStart
{
    NL;
    Print '@*'; NL
}

sub texiVerbatimEnd
{
    NL;
}

sub texiVerbatimLine
{
    s/({|}|@| )/@\1/g;
    chop;
    print DEST ".$_\@*\n";
}

###########################################################################
###########################################################################
# general processing

# emit an error message is the given macro does not exists.
sub check_Macro
{
    exists $Macro->{$_[0]} ||
	die "Error in line $.: no such macro: \\$_[0]\n";
}
sub check_Macro1
{
    (exists $Macro1a->{$_[0]} && exists $Macro1b->{$_[0]}) ||
	die "$CMD: Error in line $.: no such macro: \\$_[0]\n";
}
sub check_Macro2
{
    (exists $Macro2a->{$_[0]} && exists $Macro2b->{$_[0]} && exists $Macro2c->{$_[0]}) ||
	die "$CMD: Error in line $.: no such macro: \\$_[0]\n";
}

sub NL
{
    if (!$newline) {
	printf DEST "\n";
	if ($texiCenterLine) {
	    print DEST "\@center ";
	}
	$newline = 1;
    }
}

sub interpret_word
{
  if (@_ <= 0) {
	return;
  }
  $_ = join " ", @_;
  my ($s,$m,$a1,$a2,$r); # start, match/macro, argument1, argument2
  my $add_blank = 1;  # if true, add a blank after the word
  if ($opt_D == 2) {
      if ($nesting == 0) {
	  print "**** ";
      } else {
	  print "     ";
      }
      print "\`$_'\n";
  }

  if ($opt_H) {
      # handling of HTML table rows
      if ($inside_table == 1) {
	  if ($first_column == 1) {
	      if (/^$/) {
		  return;
	      }
	      if (/^\\hline/) {
		     if ($opt_c) {
			 Print '\n<tr class="rowstyle"><td  class="cellstyle" colspan=' . $columns . '><hr></td></tr>\n';
		     } else {
			 Print '\n<tr><td colspan=' . $columns . '><hr></td></tr>\n';
		     }
	      }
	      if ($opt_c) {
		  Print '\n<tr class="rowstyle">\n<td class="cellstyle">';
	      } else {
		  Print '\n<tr>\n<td>';
	      }
	  }
	  $first_column = 0;
      }
  } elsif ($opt_M) {
      # handling of troff table rows
      if ($inside_table == 1) {
	  if ($first_column == 1) {
	      if (/^$/) {
		  return;
	      }
	      Print 'T{\n';
	  }
	  $first_column = 0;
      }
  } elsif ($opt_T) {
      # handling of TexInfo specific stuff
      if ($nesting == 0) {
	  s'@'@@'g;
      }
      if ($inside_table == 1) {
	  if ($first_column == 1) {
	      Print '\n@item ';
	  }
	  $first_column = 0;
      }
  }

  $nesting ++;

  SWITCH: {
      /^$/                           && do {$add_blank = 0;
					    last SWITCH;
					};
      /\\verb\+([^+]*)\+/            && do {$s=$`;$m=$1;$r=$';
					    interpret_word $s;
					    PrintM $Macro1a->{'verb'};
					    &{$Prefix . "Verb"} ($m);
					    PrintM $Macro1b->{'verb'};
					    interpret_word $r;
					    last SWITCH;
					};
     /\\(".|ss)/                     && do {$s=$`;$m=$1;$r=$'; #"
					    interpret_word $s;
                                            check_Macro $m;
                                            PrintM $Macro->{$m};
					    interpret_word $r;
                                            last SWITCH;
                                        };
     /\\item\s*\[([^]]*)\]/          && do {$s=$`;$m=$1;$r=$';
					    interpret_word $s;
                                            $item_nr[$list_nest] ++;
					    &{$Prefix . "ItemWithArg"} ($m);
					    interpret_word $r;
					    last SWITCH;
					};
      /\\item\s*/                    && do {$s=$`;$r=$';
					    interpret_word $s;
                                            $item_nr[$list_nest] ++;
					    &{$Prefix . "Item"};
					    interpret_word $r;
					    last SWITCH;
					};
       # LaTeX macros with two arguments
       /\\([a-zA-Z]+){([^}]*)}{([^}]*)}/
 				     && do {$s=$`;$m=$1;$a1=$2;$a2=$3;$r=$';
                                            check_Macro2 $m;
                                            interpret_word $s;
					    PrintM $Macro2a->{$m};
					    interpret_word $a1;
					    PrintM $Macro2b->{$m};
					    interpret_word $a2;
					    PrintM $Macro2c->{$m};
					    interpret_word $r;
					    NL;
					    last SWITCH;
					};
       # Special Handling of Email and URL LaTeX macros with one argument
       /\\(URL|Email){([^}]*)}/ && ($opt_H)
 				     && do {$s=$`;$m=$1;$a1=$2;$r=$';
					    interpret_word $s;
					    PrintM $Macro2a->{$m};
					    interpret_word $a1;
					    PrintM $Macro2b->{$m};
					    interpret_word $a1;
					    PrintM $Macro2c->{$m};
					    interpret_word $r;
					    NL;
					    last SWITCH;
					};
       # LaTeX macros with one argument
       /\\([a-zA-Z]+){([^}]*)}/      && do {$s=$`;$m=$1;$a1=$2;$r=$';
					    check_Macro1 $m;
					    interpret_word $s;
					    PrintM $Macro1a->{$m};
					    interpret_word $a1;
					    PrintM $Macro1b->{$m};
					    interpret_word $r;
					    NL;
					    last SWITCH;
					};
       # Special handling of some LaTeX macros without an argument
       /\\SP\s*/                     && do {$s=$`;$m=$1;$r=$';
					    interpret_word $s;
					    if ($first_word) {
						PrintM $Macro->{"SPfirst"};
				            } else {
						PrintM $Macro->{"SP"};
				            }
					    interpret_word $r;
					    $add_blank = 0;
					    last SWITCH;
                                        };
       /\\(MANbr|TEXIbr|HTMLbr)\s*/  && do {$s=$`;$m=$1;$r=$';
					    # set $first_word to true
					    check_Macro $m;
	   	                            interpret_word $s;
					    PrintM $Macro->{$m};
					    $first_word = 1;
					    interpret_word $r;
					    $add_blank  = 0;
					    last SWITCH;
       					};
       # LaTeX macros without an argument:
       /\\([a-zA-Z]+)\s*/            && do {$s=$`;$m=$1;$r=$';
					    check_Macro $m;
	   	                            interpret_word $s;
					    PrintM $Macro->{$m};
					    interpret_word $r;
					    $add_blank = 0;
					    last SWITCH;
       					};
       /\\({|}|\$|_|#|&|-|%|,|\.|;)/ && do {$s=$`;$m=$1;$r=$';
	                                    interpret_word $s;
	                                    PrintM $Macro->{$m};
					    interpret_word $r;
					    last SWITCH;
					};
      # LaTeX Math
      /\$(<|>|<=|>=|=|<>)\$/         && do {$s=$`;$m=$1;$r=$';
					    interpret_word $s;
	                                    PrintM $Macro->{$m};
					    interpret_word $r;
					    last SWITCH;
					};
      /\$([^\$]*)\$/                 && do {$s=$`;$m=$1;$r=$';
					    interpret_word $s;
	                                    interpret_word $m;
					    interpret_word $r;
					    last SWITCH;
					};
      /&/                            && do {$s=$`;$r=$';
					    interpret_word $s;
					    &{$Prefix . "TableSep"};
					    $first_column = 0;
					    interpret_word $r;
					    last SWITCH;
					};
      /~/                            && do {$s=$`;$r=$';
					    interpret_word $s;
	                                    PrintM $Macro->{'~'};
					    interpret_word $r;
					    last SWITCH;
					};
      /\\\\/                         && do {$s=$`;$r=$';
					    interpret_word $s;
					    if ($inside_table) {
						PrintM $Macro->{'\\Tab'};
						$first_column = 1;
						if (length ($r) > 0) {
						    interpret_word $r;
						}
					    } else {
						PrintM $Macro->{'\\'};
						$first_word = 1;
						interpret_word $r;
					    }
					    $add_blank = 0;
					    last SWITCH;
					};
       /\\$|\\ /                     && do {$s=$`;$r=$';
                                            # LaTeX explicit blank \ will be
					    # represented as a single \ at
					    # the end of the word
					    interpret_word $s;
	                                    Print " ";
	                                    interpret_word $r;
					    last SWITCH;
					};
      /\\/                           && do {$s=$`;$r=$';
					    interpret_word $s;
					    interpret_word "\\$r";
					    last SWITCH;
					};
      ($opt_M == 1) && /((^\.|')+)/  && do {$s=$`;$m=$1;$r=$';
					    interpret_word $s;
					    print DEST "\\&$m";
					    $newline = 0;
					    interpret_word $r;
					    last SWITCH;
					};
      Print "$_";
  };
  $nesting --;
  Print " " if ($nesting == 0 && $add_blank);
}

sub interpret_line
{
    my $line  = $_[0]; chomp $line;
    my @words = split(/\s+/,$line);
    my $max   = $#words;
    my $i;
    my $join  = 0;   # true, if words must be joined
    my $word  = "";  # the joined word
    my $kind  = 0;   # 1: item[ .. ], 2: { .. }, 3: \verb+ .. +
    if ($max < 0) {
	# empty line marks a paragraph
	&{$Prefix . "Paragraph"};
	$first_word = 1;
	return;
    }
    for ($i = 0; $i <= $max; $i++) {
	$_ = $words[$i];
	# printf "\`$words[$i]'";
	if (/^[\s]*$/) { # skip leading blanks
	    # nothing
	} elsif ((!$join || ($kind != 3)) && /^%+/) { # skip comments
	    last;
        } else {
	    # if blanks in a { .. }, \item[ .. ], \verb+ .. + then we have to joind words
	    if ($join) {
		# check whether this is the last word to be joined
		if ($kind == 1) { # item
		    $join = index ($_, "]") == -1;
		} elsif ($kind == 2) { # braces
		    my @x = $_ =~ /[^\\]}/g;
		    $join = $#x == -1;
		} elsif ($kind == 3) { # verb
		    $join = index ($_, "+") == -1;
		}
	        $word .= " " . $words[$i];
	        if (!$join) {
		    interpret_word $word;
		    $word = "";
		}
	    } else {
		# check whether we have to join some words
		if (/\\item/) {
		    my $cnt1 = tr/[/[/;
		    my $cnt2 = tr/]/]/;
		    $join = $cnt1 != $cnt2 | $cnt1 == 0;
		    $kind = 1;
		} elsif (/\\verb/) {
		    my $cnt = tr/+/+/;
		    $join = $cnt % 2 != 0;
		    $kind = 3;
		} else {
		    my @x = $_ =~ /[^\\]{/g;
		    my @y = $_ =~ /[^\\]}/g;
		    $join = $#x != $#y;
		    $kind = 2;
		}
	        if ($join) {
		    $word = $words[$i];
		} else {
		    interpret_word $words[$i];
		}
	    }
	}
    }
    if ($join) {
	interpret_word $word;
    }
    NL;
}

sub PrintM
# print only for Macro command text
{
    if (@_ <= 0 || length ($_[0]) == 0) {
	return;
    }
    my $l = shift;
    my $c;
    $l =~ s/\\n/\n/g;
    foreach $c (split ("", $l)) {
	if ($c eq "\n") {
	    NL;
	    $newline = 0;
	} else {
	    print DEST "$c";
	}
    }
}

sub Print
{

    # printf "\`$_[0]'\n";
    if (@_ <= 0 || length ($_[0]) == 0) {
	return;
    }
    my $x = $_[0];

    unless ($x =~ /^\s*$/) {
	# if other chars than blanks are printed:
	$first_word = 0;
    }

    if (!$inside_verb) {
	# transform special characters
	$x =~ s/([äöüÄÖÜß])/$LetterCode->{"$1"}/go;
    }

    my @parts = split /\\n/, $x, -1;
    # -1: trailing \n generates an empty list element
    my $i;
    for ($i = 0; $i <= $#parts; $i++) {
	if ($newline) {
	    # skip leading blanks after a newline
	    $parts[$i] =~ s/^\s+//;
        }
	if (length($parts[$i]) > 0) {
	    if ($opt_M) {
	        $parts[$i] =~ s/\\/\\\\/g;
	        $parts[$i] =~ s/-/\\-/g;
	    }
	    printf DEST "%s", $parts[$i];
	    $newline = 0;
	}
	if ($i < $#parts) {
	    NL;
	}
    }
    $paragraph = 0;
}
#########################################################################

sub date2str
{
    @EnglishMonthName = ('','January','February','March','April','May','June','July',
			 'August','September','October','November','December');
    # split date
    my ($Year,$Month,$Day) = split (/\//,$_[0]);
    return $Day . " " . $EnglishMonthName[$Month] . " " . $Year;
}

$rcs_date=`date '+%Y/%m/%d/'`;             # date of the man-page, overwritten
                                           # by \rcsInfo
$date =  date2str ($rcs_date);
$Macro->{'today'}  = $date;

#########################################################################
my @skip;       # stack of skip-flags, 1: skip, 0: don't skip
push @skip, 0;  # synthetic "outer most" IF, don't skip
my $last_cond_clause = "";

sub handle_conditional_text
{
    $_ = $_[0];
#    printf "skip-stack: %s;\t top = %s\n", join (", ", @skip), $skip[-1];
    if (/^\s*%@%\s+IF\s+([^%]*)\s+%@%\s*$/) {
	# produce a program, which evaluates the condition:
	my $prog_cond = $1;
	$prog_cond    =~ s/(\w+)/\$$1/g;
	my $prog = "";
	my $var;
	foreach $var (keys %cond_name) {
	    if ($var ne "") {
		$prog .= "my \$$var = 1; "      # declare set names,
		    				# undeclared ones get value 0
		}
	}
	$prog .= "return ($prog_cond) ? 0 : 1;";
#	print "\n**** [$prog]\n";
	my $skip = eval $prog;
	($@ eq "") || die "$CMD: error in line $.: wrong condition of `%@% IF.. ($@)\n";
#	print "**** skip=$skip\n";

	$last_cond_clause = "IF";
	if ($skip[-1] == 1) {
	    # skip this text, since outer IF skips
	    push @skip, 1;
	} else {
	    # outer IF is not skipped, hence consider this IF
	    push @skip, $skip;
	}
    } elsif (/^\s*%@%\s+ELSE\s+%@%\s*$/) {
	($last_cond_clause =~ /IF/ && ($#skip > 0)) ||
	    die "$CMD: error in line $.: `%@% ELSE %@%' without an `%@% IF..'\n";
	$last_cond_clause = "ELSE";
	if ($skip[-2] == 0) {
	    $skip[-1] = $skip[-1]? 0 : 1;
	}
    } elsif (/^\s*%@%\s+END-IF\s+%@%\s*$/) {
	$last_cond_clause = "END-IF";
	($#skip == 0) &&
	    die "$CMD: error in line $.: `%@% END-IF %@%' without an `%@% IF..'\n";
	pop @skip;
    }
#    print "$last_cond_clause: skip = $skip[-1]\n";
}

############################################################################
# handle LaTeX output
if ($opt_L) {
    while (<SRC>) {
	if ($opt_D == 1) {
	    my $line = $_; chop $line;
	    print "--- \`$line'\n";
	}

	if (/^\s*%@%\s/) {
	    my $skip = $skip[-1];
	    handle_conditional_text ("$_");
	    # write %@% directive
	    print DEST $_;
	    next;
	}
	next if ($skip[-1] == 1);
	print DEST $_;
    }
    close (DEST);
    exit (0);
}

############################################################################
# handle non-LaTeX output

# read sections
# Variables:   $section     name of the section in uppercase letters
#              $chapter     chapter of the man page
#              $name        name of the man page
#              $Name        name of the man page in uppercase
#              $author      author of the man page
#              $tool        info about the tool set, $name is part of
#              $date        date
#              $version     version info
$started     = 0;
while (<SRC>) {
    if ($opt_D == 1) {
	my $line = $_; chop $line;
	print "--- \`$line'\n";
    }

    if ((/^\s*%@%\s/) && ($inside_verb==0)) {
	my $skip = $skip[-1];
	handle_conditional_text ("$_");
    }
    next if ($skip[-1] == 1);

    if ($inside_verb) {
        if (/^\s*\\end{verbatim}/) {
	    if ($started == 1) {
		&{$Prefix . "VerbatimEnd"};
		$inside_verb = 0;
	    }
	} else {
	    &{$Prefix . "VerbatimLine"} ($_);
	}
	next;
    }

    # remove {, } around Umlaute
    s/{(\\".)}/\1/g;      # "
    s/{(\\ss)}/\1/g;

    # normalize special characters
    s/\\"a/ä/g;
    s/\\"o/ö/g;
    s/\\"u/ü/g;
    s/\\"A/Ä/g;
    s/\\"O/Ö/g;
    s/\\"U/Ü/g;
    s/\\ss/ß/g;

    if (/^\s*\\rcsInfo \$(.*)\$/) {
	my ($rcs_id,$rcs_file,$rcs_revision,
	 $rcs_date,$rcs_time,$rcs_owner,$rcs_status,$rcs_locker) = split(/\s/,$1);
	$date = date2str ($rcs_date);
	$Macro->{'today'}  = $date;
    } elsif (/^\s*\\setDate{\\rcsInfoLongDate}/) {
	$Macro->{'Date'} = $date;
    } elsif (/^\s*\\setDate{\\today}/) {
	$Macro->{'Date'} = $date;
    } elsif (/^\s*\\setDate{([^}]*)}/) {
	$date = $1;
	$date =~ s/~/$Macro->{'~'}/g;
	$Macro->{'Date'} = $date;
    } elsif (/^\s*\\setVersion{([^}]*)}/) {
	$version            = $1;
	$versin             =~ s/~/$Macro->{'~'}/g;
	$Macro->{'Version'} = $version;
    } elsif (/^\s*\\begin{Name}{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}/) {
        $section = "Name";
        $chapter = $1;
	$name    = $2;
	$Name    = uc $name;
	$author  = $3;
	$tool    = $4;
	$title   = $5;
	$rest    = $';
	$started = 1;
	$sections[0] = $section;
	$section_cnt = 0;
	&{$Prefix . "Start"}     ($name, $chapter, $author, $tool, $title);
	&{$Prefix . "NameStart"} ($name, $chapter, $author, $tool, $title);
    } elsif (/^\s*\\end{Name}/) {
	&{$Prefix . "NameEnd"} ($name, $chapter, $author, $tool);
    } elsif (/^\s*\\begin{Table}(\[([^]]*)\])?{([^}]*)}/) {
        # \begin{Table}[width]{columns}
	if ($started == 1) {
	    $columns      = $3;
	    $column       = $_[0];
	    $inside_table = 1;
	    $first_column = 1;
	    &{$Prefix . "TableStart"} ($columns, $2);
	}
    } elsif (/^\s*\\end{Table}/) {
	if ($started == 1) {
	    $inside_table = 0;
	    $first_column = 0;
	    &{$Prefix . "TableEnd"} ($columns);
	}
    } elsif (/^\s*\\begin{Description}(\[[^]]*\])?/) {
	if ($started == 1) {
	    $list_nest++;
	    $cur_list[$list_nest] = 'descr';
	    $item_nr[$list_nest]  = 0;
	    &{$Prefix . "DescriptionStart"};
	}
    } elsif (/^\s*\\end{Description}/) {
	if ($started == 1) {
	    &{$Prefix . "DescriptionEnd"};
	    $list_nest--;
	}
    } elsif (/^\s*\\begin{description}/) {
	if ($started == 1) {
	    $list_nest++;
	    $cur_list[$list_nest] = 'descr';
	    $item_nr[$list_nest]  = 0;
	    &{$Prefix . "DescriptionStart"};
	}
    } elsif (/^\s*\\end{description}/) {
	if ($started == 1) {
	    &{$Prefix . "DescriptionEnd"};
	    $list_nest--;
	}
    } elsif (/^\s*\\begin{center}/) {
	if ($started == 1) {
	    &{$Prefix . "CenterStart"};
	}
    } elsif (/^\s*\\end{center}/) {
	if ($started == 1) {
	    &{$Prefix . "CenterEnd"};
	}
    } elsif (/^\s*\\begin{enumerate}/) {
	if ($started == 1) {
	    $list_nest++;
	    $cur_list[$list_nest] = 'enum';
	    $item_nr[$list_nest]  = 0;
	    &{$Prefix . "EnumStart"} ;
	}
    } elsif (/^\s*\\end{enumerate}/) {
	if ($started == 1) {
	    &{$Prefix . "EnumEnd"} ;
	    $list_nest--;
	}
    } elsif (/^\s*\\begin{itemize}/) {
	if ($started == 1) {
	    $list_nest++;
	    $cur_list[$list_nest] = 'item';
	    $item_nr[$list_nest]  = 0;
	    &{$Prefix . "ItemStart"} ;
	}
    } elsif (/^\s*\\end{itemize}/) {
	if ($started == 1) {
	    &{$Prefix . "ItemEnd"} ;
	    $list_nest--;
	}
    } elsif (/^\s*\\begin{verbatim}/) {
	if ($started == 1) {
	    &{$Prefix . "VerbatimStart"};
	    $inside_verb = 1;
	}
    } elsif (/^\s*\\(subsubsection|subsection|section){([^}]*)}/) {
        $kind    = $1;
	$section = $2;
	$section_cnt ++;
	$sections[$section_cnt]     = $section;
	$section_kind[$section_cnt] = $kind;
	if ($started == 1) {
	    &{$Prefix . "Section"} ($section_cnt, $kind, $section);
	}
    } elsif (/^\s*\\LatexManEnd/) {
	last;
    } elsif (/^\s*((\\begin{Name|Table|Description})|(\\(sub)?section))/) {
	die "$CMD: in line $.\n           " .
	    "Arguments of $1 are not contained in a single " .
	    "line.\n           " .
	    "Remember: all arguments of a macro must be on the same line.\n";
    } else {
	if ($started == 1) {
	    interpret_line $_;
	}
    }
}
&{$Prefix . "End"};

close DEST;

if ($opt_H || $opt_T) {
    open (TMP, "<$tmp")       || die "$CMD: Can't open file \`$tmp' for reading.\n";
    open (DEST, ">$DestFile") || die "$CMD: Can't open file \`$DestFile' for writing.\n";
    while (<TMP>) {
	if (/^\@\@INSERTION-POINT\@\@-TOC\@\@$/) {
	    if ($opt_H) {
		# Table of contents for HTML
                my $nesting     = 0; # nesting of section/subsection/subsubsection
		Print '\n<h3>Table of Contents</h3>\n';
		for ($i = 1; $i <= $section_cnt; $i++) {
                    my $cur_nesting = 0;
		    if ($section_kind[$i] eq "subsubsection") {
                        $cur_nesting = 3;
		    } elsif ($section_kind[$i] eq "subsection") {
                        $cur_nesting = 2;
		    } elsif ($section_kind[$i] eq "section") {
                        $cur_nesting = 1;
		    }
                    if ($cur_nesting > $nesting) {
			  # open a new list
                          Print '\n<ul>\n'
                    }
                    if ($cur_nesting == $nesting) {
			  # same level, close list item
		          Print '</li>\n';
                    }
                    if ($cur_nesting < $nesting) {
			  # close list and list item
			  for my $i ($cur_nesting .. $nesting-1) {
		            Print '</li>\n';
		            Print '</ul>\n';
                          }
                    }
                    # print item
		    Print "<li><a href=\"#section_$i\">";
		    interpret_word $sections[$i];
		    Print "</a>";
                    $nesting = $cur_nesting;
		}
                # close remaining lists
		for my $i (1 .. $nesting) {
		    Print '</li>\n';
		    Print '</ul>\n';
               }
	    } else {
		# Menu of sections for texi
		Print '@menu\n';
		for ($i = 2; $i <= $section_cnt; $i++) {
		    interpret_line "* " . $sections[$i] . "::";
		}
		Print '@end menu\n';
	    }
	} elsif (/\@\@INSERTION-POINT\@\@-TEXI-TOP\@\@/) {
	    # Texi-top node
	    Print '@node Top, ' . $sections[2] . ', (dir), (dir)\n';
	} elsif (/\@\@INSERTION-POINT\@\@-TEXI-SEC\@\@ (\w+) (\d+)/) {
	    # print section header for texi
	    $kind    = $1;
	    $cnt     = $2;
	    $section = $sections[$cnt];
	    Print '@node ' ;
	    interpret_word "$sections[$cnt], ";
	    interpret_word "$sections[$cnt+1], ";
	    interpret_word "$sections[$cnt-1], Top ";
	    NL;
	} else {
	    print DEST $_;
	}
    }
    close TMP;
    close DEST;
    unlink $tmp;
}

#########################################################################

## Emacs specific:
## Local Variables: ***
## mode: perl ***
## End: ***