#!/usr/bin/env perl
use strict;
$^W=1;

my $prj     = 'latex-tds';
my $file    = 'build.pl';
my $version = cvs('$Revision: 1.150 $');
my $date    = cvs('$Date: 2009/12/07 13:18:23 $');
my $author  = 'Heiko Oberdiek';
my $copyright = "Copyright 2006-2009 $author";
chomp(my $license = <<"END_LICENSE");
% $copyright
%
% This file is part of project `$prj'.
%
% It may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%  http://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Heiko Oberdiek.
%
% See `readme.txt' for a list of all files belonging to the
% project `$prj' and additional information.
%
END_LICENSE

my $time_start = time;

my $url_ctan = 'ftp://dante.ctan.org/tex-archive';
my $url_ams = 'ftp://ftp.ams.org/pub/tex';
my $url_ltxprj = 'http://www.latex-project.org/';

my @required_list = (
    'amslatex',
    'babel',
    'psnfss',
    'cyrillic',
    'graphics',
    'tools'
);
my @pkg_list = (
    'base',
    @required_list,
    $prj,
    'source',
    'tds',
    'knuth'
);

my $zip_comment = <<'END_ZIP_COMMENT';
**************************************************
* This file is part of project 'latex-tds', see  *
* CTAN:macros/latex/contrib/latex-tds/readme.txt *
**************************************************
END_ZIP_COMMENT

my $error = "!!! Error:";

my $dir_incoming = 'incoming';
my $dir_incoming_ctan = "$dir_incoming/ctan";
my $dir_incoming_ams = "$dir_incoming/ams";
my $dir_incoming_ltxprj = "$dir_incoming/ltxprj";
my $dir_build = 'build';
my $dir_lib = 'lib';
my $dir_license = 'license';
my $dir_tex = 'tex';
my $dir_patch = 'patch';
my $dir_distrib = 'distrib';
chomp(my $cwd = `pwd`);

my $jar_pdfbox_rewrite = "$cwd/$dir_lib/pdfbox-rewrite.jar";
my $jar_multivalent = "$cwd/$dir_lib/Multivalent20060102.jar";

my $file_zip_comment = "$cwd/$dir_build/zip-comment.txt";
my $file_tmp = "$cwd/$dir_build/tmp.pdf";
my $file_tmp_o = "$cwd/$dir_build/tmp-o.pdf";
my $file_ctan_distrib = "$cwd/$prj.zip";

my $file_ziptimetree = get_perl_script('ziptimetree');
my $file_adjust_checksum = get_perl_script('adjust_checksum');

my $prg_checksum    = $file_adjust_checksum;
my $prg_bibtex      = "bibtex";
my $prg_chmod       = "chmod";
my $prg_cp          = 'cp -p';
my $prg_curl        = 'curl';
my $prg_docstrip    = 'tex -shell-escape';
my $prg_epstopdf    = 'epstopdf';
my $prg_find        = 'find';
my $prg_java        = '/work/java-1.5.0/bin/java';
   # java 1.6 don't work with the used version of Multivalent
my $prg_kpsewhich   = 'kpsewhich';
my $prg_ls          = "ls";
my $prg_makeindex   = 'makeindex';
my $prg_mkdir       = 'mkdir';
my $prg_mv          = 'mv';
my $prg_patch       = "patch";
my $prg_pdflatex    = 'pdflatex';
my $prg_pdflatextds = "pdflatex -fmt=$cwd/$dir_build/latex-tds";
my $prg_pdftex      = "pdftex";
my $prg_rm          = "rm";
my $prg_rsync       = "rsync";
my $prg_sed         = "sed";
my $prg_sort        = "sort";
my $prg_unzip       = 'unzip';
my $prg_weave       = 'weave';
my $prg_wget        = 'wget';
my $prg_zip         = 'zip';
my $prg_ziptimetree = $file_ziptimetree;

$ENV{'TEXINPUTS'}  = "$cwd/tex:.:texmf/tex//:";
$ENV{'BSTINPUTS'}  = '.:texmf/bibtex//:';    # amslatex
$ENV{'TFMFONTS'}   = 'texmf/fonts/tfm//:';   # psnfss
$ENV{'VFFONTS'}    = 'texmf/fonts/vf//:';    # psnfss
$ENV{'INDEXSTYLE'} = '.:texmf/makeindex//:'; # babel

sub install ($@);

### Print title
{
    my $line = "Building $prj, $date $version, $copyright";
    print "$line\n", "=" x length($line), "\n";
}

### Option handling

my $usage = <<"END_OF_USAGE";
Usage: build.pl [options]
General options:
  --(no)download      (check for newer files, disabled by default)
  --(no)postprocess   (pdf files are postprocessed, enabled by default)
Module options:
  --all               (select all modules)
END_OF_USAGE
map { $usage .= "  --(no)$_\n"; } @pkg_list;

my $opt_download    = 0;
my $opt_postprocess = 1;
my $opt_all         = 0;
my %modules;
my @list_modules;

use Getopt::Long;
GetOptions(
    ( map { ("$_!" => \$modules{$_}); } @pkg_list ),
    'all' =>
        sub {
            $opt_all = 1;
            map { $modules{$_} = 1; } @pkg_list;
        },
    'download!'    => \$opt_download,
    'postprocess!' => \$opt_postprocess
) or die $usage;
@ARGV == 0 or die $usage;
@list_modules = grep { $modules{$_}; } @pkg_list;

info("Build modules: @list_modules");

### Format generation
if (@list_modules > 0) {
    section('Format generation');

    ensure_directory($dir_build);
    chdir $dir_build;
    run("$prg_pdflatex -ini -etex ../tex/latex-tds.ini");
    chdir $cwd;
}

### Download
{
    section('Download');

    sub download_ctan_file ($$) {
        my $file      = shift;
        my $ctan_path = shift;
        $ctan_path .= '/' if $ctan_path ne '';
        ensure_directory($dir_incoming_ctan);
        download("$dir_incoming_ctan/$file",
                 "$url_ctan/$ctan_path$file");
    }
    sub download_ctan ($$) {
        my $file      = shift;
        my $ctan_path = shift;
        download_ctan_file("$file.zip", $ctan_path);
    }
    sub download_ams ($$) {
        my $file     = shift;
        my $ams_path = shift;
        $ams_path .= '/' if $ams_path ne '';
        ensure_directory($dir_incoming_ams);
        download("$dir_incoming_ams/$file.zip",
                 "$url_ams/$ams_path$file.zip");
    }
    sub download_err ($) {
        my $name = shift;
        ensure_directory($dir_incoming_ltxprj);
        download("$dir_incoming_ltxprj/$name.err",
                 "$url_ltxprj/guides/$name.err");
    }
    sub download ($$) {
        my $file = shift;
        my $url  = shift;
        return 1 if -f $file and !$opt_download;
        info("download $url\n           --> $file");
        my $cmd = $prg_curl;
        $cmd .= " -4";
        $cmd .= " --disable-epsv";                # for ftp.ams.org
        $cmd .= " --time-cond $file" if -f $file; # download only if newer
        $cmd .= " --remote-time";                 # set file date
        $cmd .= " --output $file";                # target file
        $cmd .= " $url";                          # url
        run($cmd);
        -f $file or die "$error Download failed ($url)!\n";
    }

    download_ctan('base',          'macros/latex');
    download_ctan('doc',           'macros/latex');
    download_ctan('tools',         'macros/latex/required');
    download_ctan('graphics',      'macros/latex/required');
    download_ctan('cyrillic',      'macros/latex/required');
    download_ctan('babel',         'macros/latex/required');
    download_ctan('amslatex',      'macros/latex/required');
    download_ctan('amsrefs',       'macros/latex/contrib');
    download_ctan('psnfss',        'macros/latex/required');
    download_ctan('tds',           '');
    download_ctan('texware',       'systems/knuth/dist');
    download_ctan('mfware',        'systems/knuth/dist');
    download_ctan('etc',           'systems/knuth/dist');
    download_ctan('web',           'systems/knuth/dist');
    download_ctan('tex',           'systems/knuth/dist');
    download_ctan('mf',            'systems/knuth/dist');
    download_ctan('errata',        'systems/knuth/dist');
    download_ams('amscls',         '');
    download_ams('amsmath',        '');
    # download_ams('amsrefs',        '');
    download_ams('amslatex',       '');
    download_ams('amsrefs-tds',    'amslatex/amsrefs');
    download_ams('amsrefs-ctan',   'amslatex/amsrefs');
    download_err('manual');
    download_err('lb2');
    download_err('lgc2');
    download_err('tlc2');
}

### Remove previous build
section('Remove previous build');
{
    foreach my $pkg (@list_modules) {
        run("$prg_rm -rf $dir_build/$pkg");
        my $distribfile = "$dir_distrib/$pkg.zip";
        unlink $distribfile if -f $distribfile;
    }
    if ($opt_all) {
        unlink $file_ctan_distrib if -f $file_ctan_distrib;
    }
}

### Unpack
section('Unpacking');
{
    my $texmf_ams = "$dir_build/amslatex/texmf";

    sub unpacking ($$$) {
        my $pkg     = shift;
        my $zipfile = shift;
        my $dir     = shift;
        run("$prg_unzip $zipfile -d$dir");
    }
    sub unpack_ctan ($) {
        my $pkg = shift;
        $modules{$pkg} or return 1;
        unpacking($pkg,
                  "$dir_incoming_ctan/$pkg.zip",
                  $dir_build);
    }
    sub unpack_ams ($) {
        my $name = shift;
        $modules{'amslatex'} or return 1;
        ensure_directory($texmf_ams);
        unpacking('amslatex',
                  "$dir_incoming_ams/$name.zip",
                  "$texmf_ams");
    }
    sub unpack_psnfss ($) {
        my $name = shift;
        my $dir = "$dir_build/psnfss";
        $modules{'psnfss'} or return 1;
        unpacking('psnfss',
                "$dir/$name.zip",
                  "$dir/texmf");
    }
    sub unpack_knuth ($) {
        my $pkg = 'knuth';
        my $dir = "$dir_build/$pkg";
        my $zipfile = "$dir_incoming_ctan/$_[0].zip";
        $modules{$pkg} or return 1;
        run("$prg_unzip -j $zipfile -d$dir");
    }

    ensure_directory($dir_build);
    unpack_ctan('base');
    # replace .err files
    foreach my $name (qw[
        lb2
        lgc2
        manual
        tlc2
    ]) {
        my $file = "$dir_incoming_ltxprj/$name.err";
        my $dest = "$dir_build/base/$name.err";
        run("$prg_cp $file $dest");
    }
    if ($modules{'base'}) {
        run("$prg_rm -rf $dir_build/base/doc");
        unpacking('base',
                  "$dir_incoming_ctan/doc.zip",
                  "$dir_build/base");
        run("$prg_cp -p $dir_build/base/doc/*.tex $dir_build/base/");
    }
    map { unpack_ctan($_); } @required_list;
    if ($modules{'amslatex'}) {
        unpack_ams('amsrefs-tds');
        run("$prg_rm -rf $dir_build/amslatex/amsrefs");
        unpacking('amslatex',
                  "$dir_incoming_ams/amsrefs-ctan.zip",
                  "$dir_build/amslatex");
        unpack_ams('amslatex');
        -f "$dir_build/amslatex/classes/instr-l.tex" or
                run("$prg_unzip -j $dir_incoming_ams/amslatex.zip"
                    . " source/latex/amscls/instr-l.tex"
                    . " -d $dir_build/amslatex/classes/");
        run("$prg_rm -rf $texmf_ams/{doc,source,tex}/latex/amscls");
        run("$prg_rm -rf $texmf_ams/bibtex/bst/ams");
        unpack_ams('amscls');
        run("$prg_cp $dir_build/amslatex/classes/amsmidx.{dtx,ins}"
            . " $texmf_ams/source/latex/amscls/");
        run("$prg_cp $dir_build/amslatex/classes/amsmidx.sty"
            . " $texmf_ams/tex/latex/amscls/");
    }
    unpack_psnfss('lw35nfss');
    unpack_psnfss('freenfss');
    unpack_ctan('tds');
    unpack_knuth('texware');
    unpack_knuth('mfware');
    unpack_knuth('etc');
    unpack_knuth('web');
    unpack_knuth('tex');
    unpack_knuth('mf');
    unpack_knuth('errata');
}

### Patches
section('Patches');
{
    ; #

    if ($modules{'psnfss'}) {
        chdir "$dir_build/psnfss";
        run("$prg_checksum psfonts.dtx");
        chdir $cwd;
    }

    if ($modules{'knuth'}) {
        chdir "$dir_build/knuth";
        my @files = qw[
            trip.fot
            tripin.log
            trip.log
            trip.typ
        ];
        run("$prg_chmod -x @files");
        @files = qw[
            trap.fot
            trapin.log
            trap.log
            trap.pl
            trap.typ
        ];
        run("$prg_chmod -x @files");
        chdir $cwd;
    }

    if ($modules{'amslatex'}) {
        patch("amslatex/math/amsldoc.tex");
    }

#    if ($modules{'babel'}) {
#        map { patch("babel/$_"); } qw[
#        ];
#    }
}

### Install TDS/source
section('Install source');
{
    sub install_gen_source ($$@) {
        my $fmt  = shift;
        my $pkg  = shift;
        my @list = @_;
        $modules{$pkg} or return 1;
        chdir "$dir_build/$pkg";
        install "texmf/source/$fmt/$pkg", @list;
        chdir $cwd;
    }
    sub install_generic_source ($$@) {
        my $pkg = shift;
        my $dir = shift;
        my @list = @_;
        $modules{$pkg} or return 1;
        chdir "$dir_build/$pkg";
        install "texmf/source/$dir", @list;
        chdir $cwd;
    }
    sub install_source ($@) {
        my $pkg = shift;
        my @list = @_;
        install_gen_source('latex', $pkg, @list);
    }

    install_source 'base', qw[
        *.dtx
        *.fdd
        *.ins
        *.err
        *guide.tex
        ltnews*.tex
        ltx3info.tex
        latexbug.el
        source2e.tex
    ];
    install_source 'tools', qw[
        *.dtx
        *.ins
    ];
    install_source('graphics',
        '*.dtx',
        '*.ins',
        '*.tex'
    );
    install_source('cyrillic',
        '*.dtx',
        '*.fdd',
        '*.ins',
    );
    install_source('psnfss',
        'psnfss2e.tex',
        '*.dtx',
        '*.ins'
    );
    install_gen_source('generic', 'babel', qw[
        *.ins
        *.dtx
        *.fdd
        *.dat
        usage.tex
        tb*.tex
    ]);
    # babel/manifest.txt: to be removed in a future release
    # already removed: bghyphen.tex, bghyphsi.tex
    install_gen_source('', 'tds', qw[
        Makefile
        tds2texi.el
        tdsguide.cls
        tds.sed
        tds.tex
    ]);
    install_generic_source('knuth', 'knuth/texware', qw[
        dvitype.web
        pltotf.web
        pooltype.web
        tftopl.web
    ]);
    install_generic_source('knuth', 'knuth/mfware', qw[
        gftodvi.web
        gftype.web
        gftopk.web
        mft.web
    ]);
    install_generic_source('knuth', 'knuth/etc', qw[
        vptovf.web
        vftovp.web
    ]);
    install_generic_source('knuth', 'knuth/web', qw[
        tangle.web
        weave.web
        webman.tex
    ]);
    install_generic_source('knuth', 'knuth/tex', qw[
        glue.web
        tex.web
        trip.fot
        tripin.log
        trip.log
        tripman.tex
        tripos.tex
        trip.pl
        trip.tex
        trip.typ
    ]);
    install_generic_source('knuth', 'knuth/mf', qw[
        mf.web
        trap.fot
        trapin.log
        trap.log
        trap.mf
        trap.pl
        trap.typ
        trapman.tex
    ]);
    install_generic_source('knuth', 'knuth/errata', qw[
        errata.one
        errata.two
        errata.three
        errata.four
        errata.five
        errata.six
        errata.seven
        errata.eight
        errata.nine
        errata.ten
        errata.eleven
        errata.tex
        errorlog.tex
        logmac.tex
    ]);
}

### Patch source files after source install
section('Patches after source install');
{
    if ($modules{'base'}) {
        chdir "$dir_build/base";

        # ltdirchk.dtx must be patched to fool it in
        # not having texsys.cfg
        {
            my $file_dtx = 'ltdirchk.dtx';
            my $file_org = 'ltdirchk.dtx.org';
            rename $file_dtx, $file_org;
            open(IN, '<', $file_org) or die "$error Cannot open `$file_org'!\n";
            open(OUT, '>', $file_dtx) or die "$error Cannot write `$file_dtx'!\n";
            while (<IN>) {
                s/openin15=texsys.cfg/openin15=texsys.cfg-not-found/;
                print OUT;
            }
            close(OUT);
            close(IN);
        }

        # base: TDS:makeindex/base -> TDS:makeindex/latex
        {
            my $file_ins = 'docstrip.ins';
            my $file_org = 'docstrip.ins.org';
            rename $file_ins, $file_org;
            open(IN, '<', $file_org) or die "$error Cannot open `$file_org'!\n";
            open(OUT, '>', $file_ins) or die "$error Cannot write `$file_ins'!\n";
            while (<IN>) {
                s|makeindex/base|makeindex/latex|;
                print OUT;
            }
            close(OUT);
            close(IN);
        }

        chdir $cwd;

        patch('base/encguide.tex');
        patch('base/utf8ienc.dtx');
    }

    if ($modules{'knuth'}) {

        foreach my $file (qw[
            webman.tex
            tripman.tex
            trapman.tex
            logmac.tex
        ]) {
            patch("knuth/$file");
        }

    }

    if ($modules{'amslatex'}) {
        patch("amslatex/classes/amsclass.dtx");
    }
}

### Docstrip
section('Docstrip');
{
    sub docstrip ($$) {
        my $pkg = shift;
        my $ins = shift;
        $modules{$pkg} or return 1;
        chdir "$dir_build/$pkg";
        run("$prg_docstrip $ins.ins");
        chdir $cwd;
        1;
    }
    docstrip('base',     'unpack');
    docstrip('psnfss',   'psfonts');
    docstrip('cyrillic', 'cyrlatex');
    docstrip('graphics', 'graphics');
    docstrip('graphics', 'graphics-drivers');
    docstrip('tools',    'tools');
    docstrip('babel',    'babel');
}

section('TDS cleanup');
{
    if ($modules{'amslatex'}) {
        my $dir_tds = "$dir_build/amslatex/texmf";
        sub cleanup_tds ($@) {
            my $sub_tree = shift;

            my @list = map { glob("$dir_tds/$sub_tree/$_"); } @_;
            unlink grep { -f $_; } @list;
            map { rmdir; } grep { -d $_; } @list;
        }

        cleanup_tds 'source/latex/amscls', qw[
            *.bst
            *.template
            diffs-c.txt
        ];
        cleanup_tds 'source/latex/amsmath', qw[
            diffs-m.txt
            amstex.sty
        ];
        run("$prg_mv $dir_tds/source/latex/amsrefs/amsrefs.faq"
            . " $dir_tds/doc/latex/amsrefs/");
        cleanup_tds 'source/latex/amsrefs', qw[
            cite-x*.tex
            jr.bib
            gktest.ltb
        ];
        # CTAN:macros/latex/required/amslatex/other/*
        run("$prg_cp $dir_build/amslatex/other/amsbooka.sty"
            . " $dir_build/amslatex/texmf/tex/latex/amscls/amsbooka.sty");
        cleanup_tds 'source/latex/amsltx2', qw[
            00readme.txt
            install.txt
        ];
        cleanup_tds 'source/latex', qw[
            amsltx2
        ];
    }

    if ($modules{'babel'}) {
        my $tds_dir  = "$dir_build/babel/texmf";
        my $from_dir = "$tds_dir/source/generic/babel";

        ### Correction for *.drv files
        run("$prg_mv $from_dir/*.drv $dir_build/babel");
    }
}

### Install TDS/tex, TDS/doc files
section('Install tex doc');
{
    if ($modules{'base'}) {
        chdir "$dir_build/base";
        install 'texmf/doc/latex/base', qw[
            00readme.txt
            autoload.txt
            bugs.txt
            changes.txt
            l*.txt
            manifest.txt
            patches.txt
            t*.txt
        ];
        install 'texmf/tex/latex/base', qw[
            *.cls
            ltpatch.ltx
            idx.tex
            lablst.tex
            latexbug.tex
            lppl.tex
            testpage.tex
            ltxcheck.tex
            sample2e.tex
            small2e.tex
        ];
        install 'texmf/tex/latex/base', qw[
            texsys.cfg
        ];
        chdir $cwd;
    }

    if ($modules{'tools'}) {
        chdir "$dir_build/tools";
        install 'texmf/doc/latex/tools', qw[
            changes.txt
            manifest.txt
            readme.txt
        ];
        chdir $cwd;
    }

    if ($modules{'graphics'}) {
        chdir "$dir_build/graphics";
        install('texmf/doc/latex/graphics',
            '*.txt'
        );
        install('texmf/tex/latex/graphics',
            '*.def'
        );
        chdir $cwd;
    }

    if ($modules{'cyrillic'}) {
        chdir "$dir_build/cyrillic";
        install('texmf/doc/latex/cyrillic',
            '*.txt'
        );
        chdir $cwd;
    }

    if ($modules{'psnfss'}) {
        chdir "$dir_build/psnfss";
        install('texmf/doc/latex/psnfss',
            '*.txt'
        );
        install('texmf/doc/latex/psnfss/test',
            '*test*.tex'
        );
        install('texmf/fonts/enc/dvips/psnfss',
            '8r.enc'
        );
        install('texmf/fonts/map/dvips/psnfss',
            '*.map'
        );
        chdir $cwd;
    }

    if ($modules{'babel'}) {
        chdir "$dir_build/babel";
        install('texmf/doc/generic/babel', qw[
            *.txt
            *.heb
            *.bbl
            *.dat
            *.skeleton
            install.OzTeX*
        ]);
        chdir $cwd;
    }

    if ($modules{'tds'}) {
        chdir "$dir_build/tds";
        install('texmf/doc/tds', qw[
            README
            ChangeLog
            tds.html
        ]);
        install('texmf/doc/info', qw[
            tds.info
        ]);
        chdir $cwd;
    }

    if ($modules{'knuth'}) {
        chdir "$dir_build/knuth";
        install('texmf/doc/knuth/tex', qw[
            texbook.tex
        ]);
        install('texmf/doc/knuth/mf', qw[
            mfbook.tex
        ]);
        install('texmf/doc/knuth/errata', qw[
            cm85.bug
            mf84.bug
            tex82.bug
        ]);
        chdir $cwd;
    }

my $dummy = <<'END_DUMMY';
    if ($modules{'babel'}) {
        chdir "$dir_build/babel";
        install('texmf/tex/generic/bghyph',
            'bghyphen.txt',
            'bghyphsi.tex',
            'catmik.tex',
            'mik2t2.tex'
        );
        install('texmf/tex/generic/hyphen',
            'icehyph.tex',
            'lahyph.tex'
        );
        chdir $cwd;
    }
END_DUMMY
}

### Generate documentation for base
if ($modules{'base'}) {
    section('Documenation: base');

    sub base_guide ($) {
        my $guide = "$_[0]guide";
        run("$prg_pdflatextds -draftmode $guide");
        run("$prg_pdflatextds -draftmode $guide");
        run("$prg_pdflatextds $guide");
        install_pdf('base', $guide);
        1;
    }
    sub simple_gen ($$) {
        my $ext  = shift;
        my $base = shift;
        my $file = "$base.$ext";
        run("$prg_pdflatextds -draftmode $file");
        run("$prg_pdflatextds -draftmode $file");
        run("$prg_pdflatextds $file");
        install_pdf('base', $base);
        1;
    }
    sub complex_dtx ($) {
        my $base = shift;
        my $dtx = "$base.dtx";
        run("$prg_pdflatextds -draftmode $dtx");
        run_makeindex("$base.idx", 'gind.ist');
        run_makeindex("$base.glo", 'gglo.ist', "$base.gls");
        run("$prg_pdflatextds -draftmode $dtx");
        run_makeindex("$base.idx", 'gind.ist');
        run_makeindex("$base.glo", 'gglo.ist', "$base.gls");
        run("$prg_pdflatextds -draftmode $dtx");
        run("$prg_pdflatextds $dtx"); # hypdestopt
        install_pdf('base', "$base");
        1;
    }
    sub book_err ($) {
        my $base = shift;
        my $err = "$base.err";
        run("$prg_pdflatextds -draftmode $err");
        run("$prg_sed -i -e '"
               . 's/\\\\endinput/\\\\input{errata.cfg}\\n\\\\endinput/'
               . "' $base.cfg");
        run("$prg_pdflatextds -draftmode $err");
        run("$prg_pdflatextds -draftmode $err");
        run("$prg_pdflatextds $err"); # hypdestopt
        install_pdf('base', "$base");
        1;
    }
    chdir "$dir_build/base";
    run("$prg_pdflatextds -draftmode source2e");
    run_makeindex('source2e.idx', 'gind.ist');
    run_makeindex('source2e.glo', 'gglo.ist', 'source2e.gls');
    run("$prg_pdflatextds -draftmode source2e");
    run_makeindex('source2e.idx', 'gind.ist');
    run_makeindex('source2e.glo', 'gglo.ist', 'source2e.gls');
    run("$prg_pdflatextds -draftmode source2e");
    run("$prg_pdflatextds source2e"); # hypdestopt
    install_pdf('base', 'source2e');
    map { complex_dtx $_ } qw[
        classes
        doc
        docstrip
        letter
    ];
    map { simple_gen 'dtx', $_ } qw[
        alltt
        exscale
        fixltx2e
        graphpap
        ifthen
        inputenc
        latex209
        latexsym
        ltxdoc
        makeindx
        newlfont
        oldlfont
        proc
        slides
        syntonly
        utf8ienc
    ];
    map { simple_gen 'fdd', $_ } qw[
        cmfonts
        slifonts
    ];
    map { book_err $_ } qw[
        tlc2
        lb2
        lgc2
        webcomp
    ];
    run("$prg_sed -i -e '"
           . 's/\\\\documentclass{article}/'
           . '\\\\documentclass{article}\\n\\\\input{manual.cfg}/'
           . "' manual.err");
    run("$prg_pdflatextds -draftmode manual.err");
    run("$prg_pdflatextds -draftmode manual.err");
    run("$prg_pdflatextds manual.err"); # hypdestopt
    install_pdf('base', 'manual');
    base_guide('cfg');
    base_guide('cls');
    base_guide('cyr');
    base_guide('enc');
    base_guide('fnt');
    base_guide('mod');
    base_guide('usr');
    run("$prg_pdflatextds -draftmode doc_lppl");
    run("$prg_pdflatextds -draftmode doc_lppl");
    run("$prg_pdflatextds doc_lppl"); # hypdestopt
    run("$prg_mv doc_lppl.pdf lppl.pdf");
    install_pdf('base', 'lppl');
    run("$prg_pdflatextds -draftmode ltxcheck.drv");
    run("$prg_pdflatextds ltxcheck.drv");
    install_pdf('base', 'ltxcheck');
    my $code = <<'END_CODE';
\let\SavedDocumentclass\documentclass
\def\documentclass[#1]#2{
  \SavedDocumentclass[{#1}]{#2}
  \usepackage[colorlinks,pdfusetitle]{hyperref}
}
\input{ltx3info}
END_CODE
    $code =~ s/\s//g;
    run("$prg_pdflatextds -draftmode '$code'");
    run("$prg_pdflatextds -draftmode '$code'");
    run("$prg_pdflatextds '$code'"); # hypdestopt
    install_pdf('base', 'ltx3info');
#    for (my $i = 1; $i <= 17; $i++) {
#        my $ltnews = 'ltnews';
#        $ltnews .= '0' if $i < 10;
#        $ltnews .= $i;
#        run("$prg_pdflatex $ltnews");
#        run("$prg_pdflatex $ltnews");
#        install_pdf('base', $ltnews);
#    }
    my $ltnews = 'ltnews';
    my $lastissue = 0;
    map { $lastissue = $1 if /ltnews(\d+)\.tex/ and $lastissue < $1; }
        glob('ltnews*.tex');
    my $cmd_ltnews =
            "$prg_pdflatextds '\\def\\lastissue{$lastissue}\\input{$ltnews}'";
    run($cmd_ltnews);
    run($cmd_ltnews);
    run($cmd_ltnews);
    install_pdf('base', $ltnews);
    chdir $cwd;
}

### Generate documentation for tools
if ($modules{'tools'}) {
    section('Documentation: tools');

    chdir "$dir_build/tools";
    my @list = glob("*.dtx");
    map { s/\.dtx$//; } @list;
    foreach my $entry (@list) {
        run("$prg_pdflatextds -draftmode $entry.dtx");
        run_makeindex("$entry.idx", 'gind.ist');
        run_makeindex("$entry.glo", 'gglo.ist', "$entry.gls");
        run("$prg_pdflatextds -draftmode $entry.dtx");
        run_makeindex("$entry.idx", 'gind.ist');
        run_makeindex("$entry.glo", 'gglo.ist', "$entry.gls");
        run("$prg_pdflatextds -draftmode $entry.dtx");
        run("$prg_pdflatextds $entry.dtx"); # hypdestopt
        install_pdf('tools', $entry);
    }

    # Generate overview
    my $infile = 'manifest.txt';
    my $texfile = "$cwd/$dir_tex/tools.tex";
    my @time = localtime(time);
    my ($mday, $month, $year) = splice @time, 3, 3;
    my $release_info = sprintf "%04d/%02d/%02d Tools overview (HO)",
        $year + 1900, $month + 1, $mday;
    open(OUT, ">$texfile") or die "$error Cannot open `$texfile'!\n";
    print OUT <<"END_HEADER";
\\NeedsTeXFormat{LaTeX2e}
\\ProvidesFile{tools.tex}%
  [$release_info]
$license
\\documentclass{tools-overview}
\\begin{document}
END_HEADER
    my $entry;
    my %db;
    open(IN, $infile) or die "$error Cannot open `$infile'!\n";
    while (<IN>) {
        next if /^%/;
        next if /^\s*$/;
        if (/^(\S+)\.dtx/) {
            $entry = $1;
            $db{$entry} = '';
            next;
        }
        s/\\(\w+)/\\cs{\1}/g;
        s/(LaTeX|TeX)/\\\1\{\}/g;
        s/`([^']+)'/\\emph{\1}/g;
        s/Indent The/Indent the/; # typo
        s/Requies/Requires/; # typo
        $db{$entry} .= $_;
    }
    close(IN);
    $db{'layout'} = <<'END_LAYOUT';
    Produces an overview of the layout of the current document.
END_LAYOUT
    $db{'trace'} = <<'END_TRACE';
    The package helps to suppress and to control the amount of tracing
    output (\cs{tracingall}) by taming calc and making NFSS less noisy.
END_TRACE
    for my $entry (sort keys %db) {
        my $text = $db{$entry};
        $text =~ s/^\s*/  /mg;
        chomp $text;
        print OUT <<"END_ENTRY";
\\entry{$entry}{%
$text
}%
END_ENTRY
    }
    print OUT <<'END_TRAILER';
\end{document}
END_TRAILER
    close(OUT);
    run("$prg_pdflatextds tools.tex");
    install_pdf('tools', 'tools');
    chdir $cwd;
}

### Generate documentation for cyrillic
if ($modules{'cyrillic'}) {
    section('Documentation: cyrillic');

    chdir "$dir_build/cyrillic";
    my @list = (glob("*.dtx"), glob("*.fdd"));
    foreach my $entry (@list) {
        run("$prg_pdflatextds -draftmode $entry");
        run("$prg_pdflatextds -draftmode $entry");
        run("$prg_pdflatextds $entry"); # hypdestopt
        $entry =~ s/\.(dtx|fdd)$//;
        install_pdf('cyrillic', $entry);
    }
    chdir $cwd;
}

### Generate documentation for graphics
if ($modules{'graphics'}) {
    section('Documentation: graphics');

    chdir "$dir_build/graphics";
    my @list = glob("*.dtx");
    map { s/\.dtx$//; } @list;
    foreach my $entry (@list) {
        run("$prg_pdflatextds -draftmode $entry.dtx");
        run("$prg_pdflatextds -draftmode $entry.dtx");
        run("$prg_pdflatextds $entry.dtx"); # hypdestopt
        install_pdf('graphics', $entry);
    }
    my $code = <<'END_CODE';
\makeatletter
\let\documentclass\@@end
\input{grfguide}
END_CODE
    $code =~ s/\s//g;
    run("$prg_pdflatextds -draftmode '$code'");
    run("$prg_epstopdf a.ps");
    run("$prg_pdflatextds -draftmode grfguide");
    run("$prg_pdflatextds -draftmode grfguide");
    run("$prg_pdflatextds grfguide");
    install_pdf('graphics', 'grfguide');
    chdir $cwd;
}

### Generate documentation for amslatex
if ($modules{'amslatex'}) {
    section('Documentation: amslatex');

    sub makeindex ($) {
        my $doc = shift;
        my $style;
        $style = 'gind.ist' unless $doc eq 'amsldoc';
        run_makeindex("$doc.idx", $style);
    }

    sub bibtex ($) {
        my $doc = shift;

        if ($doc =~ /^cite-x[bh]$/) {
            run("$prg_bibtex $doc");
        }
    }

    sub generate_doc ($$) {
        my $amspkg = shift;
        my $doc = shift;
        my $ams_drv = "$cwd/$dir_tex/ams.drv";

        symlink $ams_drv, "$doc.drv";
        run("$prg_pdflatextds -draftmode $doc.drv");
        makeindex($doc);
        bibtex($doc);
        run("$prg_pdflatextds -draftmode $doc.drv");
        makeindex($doc);
        run("$prg_pdflatextds -draftmode $doc.drv");
        makeindex($doc);
        run("$prg_pdflatextds -draftmode $doc.drv") if $doc eq 'amsrefs';
        run("$prg_pdflatextds $doc.drv");
        install_pdf($amspkg, $doc);
    }

    chdir "$dir_build/amslatex/math";
    symlink '../texmf', 'texmf';
    map { generate_doc 'amsmath', $_; } qw[
        amsldoc subeqn technote testmath
        amsbsy amscd amsgen amsmath amsopn amstext amsxtra
    ];
    chdir $cwd;

    chdir "$dir_build/amslatex/classes";
    symlink '../texmf', 'texmf';
    map { generate_doc 'amscls', $_; } qw[
        amsthdoc instr-l thmtest
        amsclass amsdtx amsmidx upref
    ];
    chdir $cwd;

    chdir "$dir_build/amslatex/amsrefs";
    symlink '../texmf', 'texmf';
    map { generate_doc 'amsrefs', $_; } qw[
        cite-xa cite-xb cite-xh cite-xs
        amsrefs amsxport ifoption mathscinet pcatcode rkeyval textcmds
    ];
    chdir $cwd;
}

### Generate documentation for psnfss
if ($modules{'psnfss'}) {
    section('Documentation: psnfss');

    chdir "$dir_build/psnfss";

    run("$prg_pdflatextds -draftmode psfonts.dtx");
    run("$prg_pdflatextds psfonts.dtx");
    install_pdf('psnfss', 'psfonts');

    run("$prg_pdflatextds -draftmode psnfss2e.drv");
    run("$prg_pdflatextds -draftmode psnfss2e.drv");
    run("$prg_pdflatextds psnfss2e.drv");
    install_pdf('psnfss', 'psnfss2e');

    chdir $cwd;
}

### Generate documentation for babel
if ($modules{'babel'}) {
    section('Documentation: babel');

    sub install_babel_pdf ($) {
        install_gen_pdf('generic', 'babel', shift);
    }
    sub simple_doc ($) {
        my $file = shift;

        run("$prg_pdflatextds -draftmode $file");
        run("$prg_pdflatextds $file");
        $file =~ s/\.\w{3}$//;
        install_babel_pdf($file);
    }
    sub generate_babel_doc ($) {
        my $doc  = shift;
        my $drv  = "$cwd/$dir_tex/ams.drv";

        symlink $drv, "$doc.drv";
        run("$prg_pdflatextds -draftmode $doc.drv");
        run("$prg_pdflatextds -draftmode $doc.drv");
        run("$prg_pdflatextds -draftmode $doc.drv");
        run("$prg_pdflatextds $doc.drv");
        install_babel_pdf($doc);
    }

    chdir "$dir_build/babel";

    my $greek_fdd = 'greek-fdd.drv';
    open(OUT, ">$greek_fdd") or die "$error Cannot open `$greek_fdd'!\n";
    print OUT "\\input{greek.fdd}\n";
    close(OUT);

    map { simple_doc($_); }
        $greek_fdd, qw[
        athnum.dtx
        grmath.dtx
        grsymb.dtx
        bbidxglo.dtx
        bbcompat.dtx
        greek-usage.tex
    ];

    map { generate_babel_doc($_); } qw[
        tb1202
        tb1401
        tb1604
    ];

    run("$prg_pdflatextds -draftmode babel.tex");
    run_makeindex('babel.idx', 'bbind.ist');
    run_makeindex('babel.glo', 'bbglo.ist', 'babel.gls');
    run("$prg_pdflatextds -draftmode babel.tex");
    run_makeindex('babel.idx', 'bbind.ist');
    run_makeindex('babel.glo', 'bbglo.ist', 'babel.gls');
    run("$prg_pdflatextds -draftmode babel.tex");
    run("$prg_pdflatextds babel.tex");
    install_babel_pdf('babel');

    chdir $cwd;
}

### Generate documentation for tds
if ($modules{'tds'}) {
    section('Documentation: tds');

    chdir "$dir_build/tds";

    my $file_tds = 'tds.tex';
    my $file_tds_new = 'tds.new';

    # make nicer references and use CVS date instead of current date
    open(IN, $file_tds) or die "$error Cannot open `$file_tds'!\n";
    open(OUT, '>', $file_tds_new) or die "$error Cannot write `$file_tds_new'!\n";
    while (<IN>) {
        s/Appendix~\\ref/\\appref/g;
        s/Section~\\ref/\\secref/g;
        if (/^% \$Id:.* (\d\d\d\d)\/(\d\d)\/(\d\d) /) {
            print OUT <<"END_TEXT";
\\year=$1\\relax
\\month=$2\\relax
\\day=$3\\relax
END_TEXT
        }
        print OUT;
    }
    close(OUT);
    close(IN);

    unlink('tds.aux');
    run("$prg_pdflatextds -draftmode $file_tds_new");
    run("$prg_pdflatextds -draftmode $file_tds_new");
    run("$prg_pdflatextds $file_tds_new");
    install_gen_pdf('', 'tds', 'tds');

    chdir $cwd;
}

### Generate documentation for knuth
if ($modules{'knuth'}) {
    section('Documentation: knuth');

    chdir "$dir_build/knuth";

    my $knuth_drv = "$cwd/$dir_tex/knuth.drv";

    sub generate_web_doc ($@) {
        my $dir = shift;
        my @list = @_;

        foreach my $entry (@list) {
            symlink $knuth_drv, "$entry.drv";
            run("$prg_weave $entry.web")
                    unless $entry eq 'webman'
                        or $entry eq 'tripman'
                        or $entry eq 'trapman';
            run("$prg_pdftex -draftmode $entry.drv");
            run("$prg_pdftex $entry.drv");
            install_gen_pdf('knuth', $dir, $entry);
        }
    }

    generate_web_doc('texware', qw[
        dvitype
        pltotf
        pooltype
        tftopl
    ]);
    generate_web_doc('mfware', qw[
        gftodvi
        gftype
        gftopk
        mft
    ]);
    generate_web_doc('etc', qw[
        vptovf
        vftovp
    ]);
    generate_web_doc('web', qw[
        tangle
        weave
        webman
    ]);
    generate_web_doc('tex', qw[
        glue
        tex
    ]);
    generate_web_doc('mf', qw[
        mf
    ]);

    run("$prg_pdftex tripman");
    install_gen_pdf('knuth', 'tex', 'tripman');

    run("$prg_pdftex trapman");
    install_gen_pdf('knuth', 'mf', 'trapman');

    symlink "$cwd/$dir_tex/errorlog.drv", 'errorlog.drv';
    run("$prg_pdftex errorlog.drv");
    install_gen_pdf('knuth', 'errata', 'errorlog');

    # last bug date is used for errata.tex's today
    {
        open(IN, '<', 'errata.tex') or die "$error Cannot open `errata.tex'!\n";
        my @lines = <IN>;
        close(IN);

        my ($day, $month, $year) = (0, 0, 0);
        sub xdays {
            my $y = shift;
            my $m = shift;
            $m -= 1;
            my $d = shift;
            return $y*12*31 + $m*31 +$d;
        }
        foreach $_ (@lines) {
            next unless /^\\bugonpage/;
            next unless m|\((\d\d)/(\d\d)/(\d\d)\)\s*$|;
            my ($d, $m, $y) = ($2, $1, $3);
            $y += 1900;
            $y += 100 if $y < 1970;
            if (xdays($y, $m, $d) > xdays($year, $month, $day)) {
                $year = $y;
                $month = $m;
                $day = $d;
            }
        }

        open(OUT, '>', 'errata.new') or die "$error Cannot open `errata.new'!\n";
        print OUT "\\year=$year\n";
        print OUT "\\month=$month\n";
        print OUT "\\day=$day\n";
        print OUT "\\input errata.tex\n";
        print OUT "\\endinput\n";
        close(OUT);
    }
    foreach my $entry (qw[
        one
        two
        three
        four
        five
        six
        seven
        eight
        nine
        ten
        eleven
        new
    ]) {
        symlink "$cwd/$dir_tex/errata.drv", "errata_$entry.tex";
        run("$prg_pdftex errata_$entry.tex");
    }
    symlink "$cwd/$dir_tex/errata.all", 'errata.all';
    run("$prg_pdftex errata.all");
    install_gen_pdf('knuth', 'errata', 'errata');

    chdir $cwd;
}

### Module source
if ($modules{'source'}) {
    section('Module source');

    my $dir_dest = "$dir_build/source/texmf/source/latex/latex-tds";
    my $dir_scripts = "$dir_build/source/texmf/scripts";

    install $dir_dest, qw[
        build.pl
        readme.txt
    ];
    install "$dir_dest/tex", glob("$dir_tex/*.*");
    install "$dir_dest/patch", glob("$dir_patch/*.*");
    install "$dir_dest/lib", $file_ziptimetree;
    install "$dir_dest/lib", $file_adjust_checksum;
    install "$dir_dest/license", "$dir_license/lppl.txt";
    install "$dir_dest/license/ziptimetree", "$dir_license/ziptimetree/lgpl.txt";
    install $dir_distrib, 'readme.txt';
}

### Module latex-tds
if ($modules{$prj}) {
    section('Module latex-tds');

    my $dir = "$dir_build/$prj";
    ensure_directory($dir);
    my $cmd_rsync = "$prg_rsync " . join ' ', qw[
        --recursive
        --times
        --perms
        --owner
        --group
        --hard-links
    ];
    for (@pkg_list) {
        next if $_ eq $prj;
        my $reftree = "$dir_build/$_";
        next unless -d "$reftree/texmf";
        run("$cmd_rsync --link-dest=$cwd/$reftree $reftree/texmf $dir");
    }
}

### Pack result
section('Distrib');
{
    ensure_directory($dir_distrib);

    # write zip comment file
    open(OUT, '>', $file_zip_comment)
            or die "$error Cannot write file `$file_zip_comment'!\n";
    print OUT $zip_comment;
    close OUT;

    for my $pkg (@list_modules) {
        my $dir_tds = "$dir_build/$pkg/texmf";
        my $file_distrib = "$cwd/$dir_distrib/$pkg.tds.zip";
        if (-d $dir_tds) {
            run_zip($file_distrib, $dir_tds);
        }
        else {
            print "!!! Warning: Missing TDS tree for `$pkg'!\n";
        }
    }

    if ($opt_all) {
        chdir $dir_distrib;
        my $cmd = "$prg_zip -0 $file_ctan_distrib readme.txt";
        for my $pkg (sort @pkg_list) {
            $cmd .= " $pkg.tds.zip";
        }
        run($cmd);
        chdir $cwd;
    }
}

### Display result
section('Result');
{
    for my $pkg (@list_modules) {
        my $file = "$dir_distrib/$pkg.tds.zip";
        if (-f $file) {
            system("$prg_ls -l $file");
            system("$prg_ls -l $dir_distrib/readme.txt")if $pkg eq 'source';
        }
        else {
            print "!!! Warning: Missing distribution for `$pkg'!\n";
        }
    }
    if ($opt_all) {
        system("$prg_ls -l $file_ctan_distrib");
    }

    # display time
    my $time_diff = time - $time_start;
    my $time_str = sprintf "%d:%02d:%02d\n",
                           $time_diff / 3600,
                           ($time_diff % 3600) / 60,
                           ($time_diff % 3600) % 60;
    $time_str =~ s/^0:0?//;
    print "* Elapsed time: $time_str\n";
}

sub install ($@) {
    my $dir_target = shift;
    my @list       = @_;

    ensure_directory($dir_target);
    run("$prg_cp @list $dir_target/");
    1;
}

sub install_gen_pdf ($$$) {
    my $fmt         = shift;
    my $pkg         = shift;
    my $file_base   = shift;
    my $file_source = "$file_base.pdf";
    my $dir_dest    = "texmf/doc/$fmt/$pkg";
    my $file_dest   = "$dir_dest/$file_base.pdf";

    ensure_directory($dir_dest);
    if ($opt_postprocess) {
        printsize($file_source, 0);
        if (-f $jar_pdfbox_rewrite) {
            run("$prg_java -jar $jar_pdfbox_rewrite $file_source $file_tmp");
        }
        else {
            run("$prg_cp $file_source $file_tmp");
        }
        run("$prg_java -cp $jar_multivalent tool.pdf.Compress -old $file_tmp");
        run("$prg_mv $file_tmp_o $file_dest");
        printsize($file_dest, 1);
    }
    else {
        run("$prg_cp $file_source $file_dest");
    }
    1;
}
sub install_pdf ($$) {
    my $pkg       = shift;
    my $file_base = shift;

    install_gen_pdf('latex', $pkg, $file_base);
}

sub printsize ($$) {
    my $file  = shift;
    my $modus = shift;
    my $size  = (stat($file))[7];
    $size =~ s/(\d)(\d{6})$/$1.$2/;
    $size =~ s/(\d)(\d{3})$/$1.$2/;
    $size = " " x (9 - length($size)) . $size;
    if ($modus == 0) {
        print "*" x 78 . "\n";
        print "* $size  $file\n";
    }
    else {
        print "* $size  $file\n";
        print "*" x 78 . "\n";
        print "\n";
    }
}

sub ensure_directory ($) {
    my $dir = shift;

    return 1 if -d $dir;
    run("$prg_mkdir -p '$dir'");
    return 1 if -d $dir;
    die "$error Cannot generate directory `$dir'!\n";
}

sub section ($) {
    my $title = shift;

    print "\n=== $title ===\n";
    1;
}

sub run ($) {
    my $cmd = shift;

    info("system: $cmd");
    my $ret = system($cmd);
    if ($ret != 0) {
        if ($? == -1) {
            die "$error Failed to execute: $!\n";
        }
        elsif ($? & 127) {
            die "$error Child died with signal "
                . ($? & 127)
                . (($? & 128) ? ' with coredump' : '')
                . "!\n";
        }
        else {
            die "$error Child exited with value " . ($? >> 8) . "!\n";
        }
    }
    1;
}

sub run_makeindex ($;$$) {
    my $input_file  = shift;
    my $style_file  = shift;
    my $output_file = shift;

    return 1 unless -f $input_file;
    my $cmd = $prg_makeindex;
    $cmd .= " -s $style_file" if $style_file;
    $cmd .= " -o $output_file" if $output_file;
    $cmd .= " $input_file";
    run($cmd);
}

sub run_zip ($$) {
    my $zip_file = shift;
    my $dir_start = shift;
    run("$prg_ziptimetree --verbose --noroot $zip_file $dir_start");
    run("$prg_zip -z $zip_file <$file_zip_comment");
}

sub info ($) {
    my $msg = shift;
    print "* $msg\n";
    1;
}

sub cvs ($) {
    $_ = shift;
    s/^\$\w+:?\s*(\S*).*\$$/$1/;
    $_ = "v$_" if /\./;
    $_;
}

sub patch ($) {
    my $file  = shift;
    my $patch = $file;
    $patch =~ s/^.*\/([^\/]+)$/$1/;
    run("$prg_patch $dir_build/$file $dir_patch/$patch.diff");
}

sub get_perl_script ($) {
    # Either the source of latex-tds is unpacked as TDS tree,
    # then the perl script is below TDS:scripts/
    # or it can be put into the lib directory $dir_lib that I am using.
    my $script = shift;
    if (-f "$cwd/$dir_lib/$script.pl") {
        $script = "$cwd/$dir_lib/$script.pl";
    }
    else {
        if (-f "$cwd/../../../scripts/latex-tds/$script.pl") {
            $script = "$cwd/../../../scripts/latex-tds/$script.pl";
        }
        else {
            $script = "$cwd/../../../scripts/$script/$script.pl";
        }
    }
    die "$error Script $script.pl not found!\n" unless -f $script;
    run("$prg_chmod +x $script") unless -x $script;
    die "$error Script $script is not executable!\n" unless -x $script;
    $script;
}

__END__
