eval '(exit $?0)' && eval 'exec perl -wST "$0" ${1+"$@"}'
  & eval 'exec perl -wST "$0" $argv:q'
    if 0;

# Copyright (C) 2011-2012 Free Software Foundation, Inc.
#
# This file is part of GnuTLS.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this file.  If not, see <https://www.gnu.org/licenses/>.

use constant NORMAL => 0;
use constant SKIP => 1;
use constant ITEMIZE => 2;
use constant VERBATIM => 3;
use constant ENUMERATE => 4;
use constant TABLE_ITEMIZE => 5;
use constant MULTITABLE => 6;
use constant EXAMPLE => 7;
use constant SMALL_EXAMPLE => 8;
use constant QUOTE => 9;
use constant FLOAT => 10;
use constant FLOAT_TABLE => 11;
use constant MULTITABLE_INIT => 12;

sub unescape()
{
my $prefix=$_[0];
my $suffix=$_[1];
	$suffix =~ s/\\//g;
	return "$prefix\{$suffix\}";
}

sub funcref()
{
my $prefix = $_[0];
my $suffix=$_[0];
	$suffix =~ s/\\//g;
	$prefix =~ s/\\_/\\_\\-/g;

	return "\\funcref\{$prefix\}\{$suffix\}";
}

sub showfunc()
{
my $prefix = $_[0];
my $suffix = $_[1];
	$suffix =~ s/\\//g;
	$suffix =~ s/\,/\}\{/g;

	return "\\showfunc$prefix\{$suffix\}";
}

sub showfuncdesc()
{
my $suffix = $_[0];
	$suffix =~ s/\\//g;

	return "\\showfuncdesc\{$suffix\}";
}

sub showenumdesc()
{
my $prefix = $_[0];
my $suffix = $_[1];
	$prefix =~ s/\\//g;
	return "\\showenumdesc\{$prefix\}\{$suffix\}";
}

my $punescape = \&unescape;
my $pfuncref = \&funcref;
my $pshowfunc = \&showfunc;
my $pshowfuncdesc = \&showfuncdesc;
my $pshowenumdesc = \&showenumdesc;
my $mode = NORMAL;
my $num_args = $#ARGV + 1;

if ($num_args != 1 || $ARGV[0] eq "-h" || $ARGV[0] eq "--help") {
        print "Usage: " . "texi2latex infile\n";
        exit 0;
}
open (FILE, "< $ARGV[0]") or die "Cannot open $ARGV[0]";

my $match = "[\\w\\d-\\.\\/\\@\\:\_\\\\\#]";
my $spacematch = "[\\s\\w\\d-\\.\\/\\@\\#\\:]";
my $mathmatch = "[\\s\\w\\d-\\.\\/\\:\\(\\)\\+\\/\\^\\'\\=\{\}\\\\\\,]";
my $underscorematch = "[\\s\\w\\d-\\.\\/\\@\\_\\\\\:\\~]";
my $codematch = "[\\s\\w\\d-\\.\\/\\@\\_\\\\\:\\-\\\"\+\\%\\#\\,]";
my $extcodematch = "[\\s\\w\\d-\\.\\/\\@\\_\\\\\:\\-\\\"\+\\%\\,\\{\\}]";
my ($line, $prev_mode);
my ($verbatim, $label);
my @stack = ();

while ($line = <FILE>) {
	$verbatim = 0;

        if ($mode == SKIP) {
#print "%menu: $line";
                if ($line =~ m/\@end /) {
                        $mode = pop(@stack);
                }
		$prev_mode = $mode;
                next;
        } elsif ($mode == ITEMIZE) {
#print "%itemize: $line";
                if ($line =~ s/\@end itemize/\\end{itemize}/g) {
                        $mode = pop(@stack);
                }
                $line =~ s/\@item (.+)/\\item $1/g;
                $line =~ s/\@item/\\item/g;
		$prev_mode = $mode;
        } elsif ($mode == ENUMERATE) {
                if ($line =~ s/\@end itemize/\\end{enumerate}/g) {
                        $mode = pop(@stack);
                }
                if ($line =~ s/\@end enumerate/\\end{enumerate}/g) {
                        $mode = pop(@stack);
                }
                $line =~ s/\@item(.*)/\\item $1/g;
                $line =~ s/\@item/\\item/g;
		$prev_mode = $mode;
        } elsif ($mode == FLOAT) {
                if ($line =~ s/\@end float/\\label\{$label\}\n\\end{figure}/g) {
                        $mode = pop(@stack);
                }
                $line =~ s/\@image\{(\w)\,($spacematch)\}/\\includegraphics\[width=$2\]\{$1\}/g;
		$line =~ s/\@caption\{/\\caption\{/g;
		$prev_mode = $mode;
        } elsif ($mode == FLOAT_TABLE) {
                if ($line =~ s/\@end float/\\label\{$label\}\n\\end{table}/g) {
                        $mode = pop(@stack);
                } else {
			$line =~ s/\@caption\{/\\caption\{/g;

			if ($line =~ m/\@multitable/) {
				push(@stack, FLOAT_TABLE);
				$line =~ s/\@multitable \@columnfractions ([\.\d]+) ([\.\d]+)$/\n\\begin{tabular}{|p{$1\\linewidth}|p{$2\\linewidth}|}\n\\hline\n/g;
				$line =~ s/\@multitable \@columnfractions ([\.\d]+) ([\.\d]+) ([\.\d]+)$/\n\\begin{tabular}{|p{$1\\linewidth}|p{$2\\linewidth}|p{$3\\linewidth}|}\n\\hline\n/g;
				$line =~ s/\@multitable \@columnfractions ([\.\d]+) ([\.\d]+) ([\.\d]+) ([\.\d]+)$/\n\\begin{tabular}{|p{$1\\linewidth}|p{$2\\linewidth}|p{$3\\linewidth}|p{$4\\linewidth}|}\n\\hline\n/g;
				$line =~ s/\@multitable \@columnfractions ([\.\d]+) ([\.\d]+) ([\.\d]+) ([\.\d]+) ([\.\d]+)$/\n\\begin{tabular}{|p{$1\\linewidth}|p{$2\\linewidth}|p{$3\\linewidth}|p{$4\\linewidth}|p{$5\\linewidth}|}\n\\hline\n/g;
			}
			
			goto multitable;
		}
		$prev_mode = $mode;
        } elsif ($mode == TABLE_ITEMIZE) {
                if ($line =~ s/\@end table/\n\\end{itemize}/g) {
                        $mode = pop(@stack);
                }
		chomp $line;
		if ($line eq "") {
			next;
		}
		$line .= "\n";

		$line =~ s/\@item (.+)/\\item $1 /g;
		$line =~ s/\@itemx (.+)/\\item $1 /g;

		$prev_mode = $mode;
        } elsif ($mode == MULTITABLE) {
multitable:
                if ($line =~ s/\@end multitable/\\\\\n\\hline\n\\end{tabular}/g) {
                        $mode = pop(@stack);
                } elsif ($line =~ s/\@itemize/\\begin{itemize}/g) {
                        $mode = ITEMIZE;
                        push(@stack, MULTITABLE);
                } else {
			chomp $line;
			if ($line eq "") {
				next;
			}
			$line .= "\n";
			$line =~ s/\@tab/\&/g;
			if ($line =~ m/\@headitem/) {
				$line =~ s/\@headitem (.+)/$1\\\\\n\\hline\n\\hline/g;
				$prev_mode = MULTITABLE_INIT;
			} else {
				if ($prev_mode == MULTITABLE_INIT) {
					$line =~ s/\@item (.+)/$1/g;
					$line =~ s/\@itemx (.+)/$1/g;
					$prev_mode = MULTITABLE;
				} elsif ($prev_mode == MULTITABLE) {
					$line =~ s/\@item (.+)/\\\\\n\\hline\n$1/g;
					$line =~ s/\@itemx (.+)/\\\\\n\\hline\n$1/g;
				}
			}
		}

        } elsif ($mode == VERBATIM) {
                if ($line =~ s/\@end verbatim/\\end{verbatim}/g) {
                        $mode = pop(@stack);
                }
		$verbatim = 1;
		$prev_mode = $mode;
        } elsif ($mode == QUOTE) {
                if ($line =~ s/\@end quotation/\\end{quote}/g) {
                        $mode = pop(@stack);
                }
		$prev_mode = $mode;
        } elsif ($mode == EXAMPLE) {
                if ($line =~ s/\@end example/\\end{example}/g) {
                        $mode = pop(@stack);
                }
		$line =~ s/\@\{/{/g;
		$line =~ s/\@}/}/g;
		$verbatim = 1;

		$prev_mode = $mode;
        } elsif ($mode == SMALL_EXAMPLE) {
                if ($line =~ s/\@end smallexample/\\end{smallexample}/g) {
                        $mode = pop(@stack);
                }
		$line =~ s/\@\{/\{/g;
		$line =~ s/\@}/\}/g;
		$verbatim = 1;

		$prev_mode = $mode;
        } else {
		$prev_mode = $mode;

		$line =~ s/\@iftex/%c /g;
		$line =~ s/\@end iftex/%c /g;
                $line =~ s/\@anchor (.+)/\\label{$1}/g;
		$line =~ s/\@anchor\{($spacematch+)\}/\\label{$1}/g;
		if ($line =~ s/\@subsection (.+)/\\subsection{$1}/g) {
			if ($label ne '') {
				$line .= "\\label{$label}\n";
			}
		}

		if ($line =~ s/\@subsubsection (.+)/\\subsubsection{$1}/g) {
			if ($label ne '') {
				$line .= "\\label{$label}\n";
			}
		}

		$line =~ s/\@subsubheading (.+)/\\subsubsection\*{$1}/g;
		$line =~ s/\@subheading (.+)/\\subsection\*{$1}/g;
		$line =~ s/\@heading (.+)/\\section\*{$1}/g;

                if ($line =~ s/\@section (.+)/\\section{$1}/g) {
			if ($label ne '') {
				$line .= "\\label{$label}\n";
			}
		}

                if ($line =~ s/\@chapter (.+)/\\chapter{$1}/g) {
			if ($label ne '') {
				$line .= "\\label{$label}\n";
			}
		}
		if ($line =~ s/\@appendix (.+)/\\chapter{$1}/g) {
			if ($label ne '') {
				$line .= "\\label{$label}\n";
			}
		}

                if ($line =~ m/\@node (.+)/) {
			$label = $1;
			next;
		} else {
			$label = '';
		}
                if ($line =~ s/\@menu//g) {
                        $mode = SKIP;
                        push(@stack, NORMAL);
			next;
                }
                if ($line =~ s/\@ignore//g) {
                        $mode = SKIP;
                        push(@stack, NORMAL);
			next;
                }
                if ($line =~ s/\@ifnottex//g) {
                        $mode = SKIP;
                        push(@stack, NORMAL);
			next;
                }
                if ($line =~ s/\@itemize \@bullet/\\begin{itemize}/g) {
                        $mode = ITEMIZE;
                        push(@stack, NORMAL);
                }
                if ($line =~ s/\@itemize/\\begin{itemize}/g) {
                        $mode = ITEMIZE;
                        push(@stack, NORMAL);
                }
                if ($line =~ s/\@float Figure\,(.*)/\\begin{figure}[htbp]\n\\centering/g) {
			$label = $1;
                        push(@stack, NORMAL);
                        $mode = FLOAT;
                }
                if ($line =~ s/\@float Table\,(.*)/\\begin{table}[htbp]\n\\centering/g) {
			$label = $1;
                        push(@stack, NORMAL);
                        $mode = FLOAT_TABLE;
                }
                if ($line =~ s/\@enumerate/\\begin{enumerate}/g) {
                        push(@stack, NORMAL);
                        $mode = ENUMERATE;
                }
                if ($line =~ s/\@table .*/\n\\begin{itemize}/g) {
                        push(@stack, NORMAL);
                        $mode = TABLE_ITEMIZE;
                }
                if ($line =~ s/\@multitable \@columnfractions ([\.\d]+) ([\.\d]+)$/\n\\begin{tabular}{|p{$1\\linewidth}|p{$2\\linewidth}|}\n\\hline\n/g) {
                        push(@stack, NORMAL);
                        $mode = MULTITABLE;
                }
                if ($line =~ s/\@multitable \@columnfractions ([\.\d]+) ([\.\d]+) ([\.\d]+)$/\n\\begin{tabular}{|p{$1\\linewidth}|p{$2\\linewidth}|p{$3\\linewidth}|}\n\\hline\n/g) {
                        push(@stack, NORMAL);
                        $mode = MULTITABLE;
                }
                if ($line =~ s/\@multitable \@columnfractions ([\.\d]+) ([\.\d]+) ([\.\d]+) ([\.\d]+) ([\.\d]+)$/\n\\begin{tabular}{|p{$1\\linewidth}|p{$2\\linewidth}|p{$3\\linewidth}|p{$4\\linewidth}|p{$5\\linewidth}|}\n\\hline\n/g) {
                        push(@stack, NORMAL);
                        $mode = MULTITABLE;
                }
                if ($line =~ s/\@example$/\\begin{example}/g) {
                        push(@stack, NORMAL);
                        $mode = EXAMPLE;
                }
                if ($line =~ s/\@smallexample/\\begin{smallexample}/g) {
                        push(@stack, NORMAL);
                        $mode = SMALL_EXAMPLE;
                }
                if ($line =~ s/\@verbatim$/\\begin{verbatim}/g) {
                        push(@stack, NORMAL);
                        $mode = VERBATIM;
                }
                if ($line =~ s/\@quotation$/\\begin{quote}/g) {
                        push(@stack, NORMAL);
                        $mode = QUOTE;
                }
        }

	if ($verbatim == 0) {
		$line =~ s/\</\$<\$/g;
		$line =~ s/\>/\$>\$/g;
		$line =~ s/\_/\\_/g;
		$line =~ s/\~/\\~/g;
		$line =~ s/\^/\\\\textasciicircum/g;
		$line =~ s/\%(?!c)/\\%/g;
		$line =~ s/\#/\\\#/g;
		$line =~ s/\@-/\\-/g;
		$line =~ s/\@"i/\\"{\i}/g;
                $line =~ s/\@verbatiminclude (.*)/\\examplefile{\.\.\/$1}/g;
		$line =~ s/\@image\{($match+)\,($match+)\}/\\includegraphics\[width\=$2\]\{\.\.\/$1\}/g;
		$line =~ s/\@samp\{($spacematch+)\}/$1/g;
		$line =~ s/\@strong\{/\{\\bf /g;
		$line =~ s/\@noindent.*//g;
		$line =~ s/\@exampleindent.*//g;
		$line =~ s/\@c (.*)/\% $1/g;
		$line =~ s/\@math\{($mathmatch+)\}/\$$1\$/g;
		$line =~ s/\@acronym\{($spacematch+)\}/\\acronym{$1}/g;
		$line =~ s/\@acronym\{/\\acronym{/g;
		$line =~ s/\s*\@xcite\{($match+)\}/~\\cite{$1}/g;
		$line =~ s/\s*\@xcite\{($match+)\,($match+)\}/~\\cite{$1,$2}/g;
		$line =~ s/\@footnote\{/\\footnote{/g;
		$line =~ s/\@tindex (.+)/\\index{$1}/g;
		if ($line =~ s/\@include (.+)/\\input{$1}/g) {
			$line =~ s/\.texi/\.tex/g;
			$line =~ s/(\\input)\{($underscorematch+)\}/$punescape->($1,$2)/ge;
		}
		$line =~ s/\@cindex (.+)/\\index{$1}/g;
		$line =~ s/\@pindex (.+)/\\index{$1}/g;
		$line =~ s/\@url\{($underscorematch+)\}/\\url{$1}/g;
		#$line =~ s/\s*\@euro\{\}/\~\\euro/g;
		$line =~ s/\@page/\\newpage/g;
		$line =~ s/\@file\{($spacematch+)\}/\\file{$1}/g;
		$line =~ s/\@code\{/\\code{/g;
		$line =~ s/\@option\{($codematch+)\}/\\command{$1}/g;
		$line =~ s/\@command\{($codematch+)\}/\\command{$1}/g;
		$line =~ s/\@ref\{/\\myref\{/g;
		$line =~ s/\@emph\{($spacematch+)\}/\\emph{$1}/g;
		$line =~ s/\@xref\{/\\myref\{/g;
		$line =~ s/\@funcref\{($codematch+)\}/$pfuncref->($1)/ge;
		$line =~ s/\@funcintref\{($codematch+)\}/$pfuncref->($1)/ge;
		$line =~ s/\@showfunc([A-Z])\{($codematch+)\}/$pshowfunc->($1,$2)/ge;
		$line =~ s/\@showfuncdesc\{($codematch+)\}/$pshowfuncdesc->($1)/ge;
		$line =~ s/\@showenumdesc\{($codematch+),($extcodematch+)\}/$pshowenumdesc->($1,$2)/ge;
		$line =~s/\@pxref\{($spacematch+),($spacematch+)\}/\\myref\{$1\}/g;
		$line =~ s/\@pxref\{/\\myref\{/g;
		$line =~ s/\@center (.*)/\\begin{center}\n$1\n\\end{center}/g;
		if ($line =~ m/\@email/) {
			$line =~ s/\@email\{(.+)\}/$1/g;
		}
		$line =~ s/\@\@/@/g;

		#when a myref{} contains underscores remove them
		$line =~ s/(\\myref)\{($underscorematch+)\}/$punescape->($1,$2)/ge;
	}
	$line =~ s/\@\@/\@/g;

        print $line;
}
close (FILE);

exit 0;
