#!/usr/bin/perl -w
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if $running_under_some_shell;
##
##  divert -- Diversion Filter
##  Copyright (c) 1997-2001 Ralf S. Engelschall, All Rights Reserved.
##  Copyright (c) 1999-2001 Denis Barbier, All Rights Reserved.
##

require 5.003;

BEGIN { $^W = 0; } # get rid of nasty warnings

use lib "/usr/lib/wml/perl/lib";
use lib "/usr/lib/wml/perl/lib/mips-linux-thread-multi";

use Getopt::Long 2.13;
use IO::Handle 1.15;
use IO::File 1.06;

#
#   process command line
#
sub usage {
    print STDERR "Usage: divert [options] [file]\n";
    print STDERR "\n";
    print STDERR "Options:\n";
    print STDERR "  -o, --outputfile=<file>  set output file instead of stdout\n";
    print STDERR "  -q, --quiet              quiet mode (no warnings)\n";
    print STDERR "  -v, --verbose            verbose mode\n";
    exit(1);
}
$opt_v = 0;
$opt_q = 0;
$opt_o = '-';
$Getopt::Long::bundling = 1;
$Getopt::Long::getopt_compat = 0;
if (not Getopt::Long::GetOptions(
    "v|verbose",
    "q|quiet",
    "o|outputfile=s")) {
    usage();
}
sub verbose {
    my ($str) = @_;
    if ($opt_v) {
        print STDERR "** Divert:Verbose: $str\n";
    }
}
sub error {
    my ($str) = @_;
    print STDERR "** Divert:Error: $str\n";
    exit(1);
}
sub warning {
    my ($file, $line, $str) = @_;
    if (not $opt_q) {
        print STDERR "** Divert:Warning: $file:$line: $str\n";
    }
}

#
#   open input file and read into buffer
#
my $file;
my $in;

if (($#ARGV == 0 and $ARGV[0] eq '-') or $#ARGV == -1) {
    $in = new IO::Handle;
    $file = 'STDIN';
    $in->fdopen(fileno(STDIN), "r") || error("cannot load STDIN: $!");
}
elsif ($#ARGV == 0) {
    $in = new IO::File;
    $file = $ARGV[0];
    $in->open($file) || error("cannot load $file: $!");
}
else {
    usage();
}


##
##   Pass 1: Parse the input data into disjunct location buffers
##           Each location buffer contains plain text blocks and
##           location pointers.
##

my $location = 'main';                       # currently active location
my @LOCSTACK = ('null');                     # stack of remembered locations
my %BUFFER   = ('null' => [], 'main' => []); # the location buffers
my %OVRWRITE = ();                           # the overwrite flags
my $line = 0;
my $remain;

while (<$in>) {
    $remain = $_;
    $line++;
    while ($remain) {
        if (   $remain =~ s|^<<([a-zA-Z][a-zA-Z0-9_]*)>>||
            or $remain =~ s|^{#([a-zA-Z][a-zA-Z0-9_]*)#}||) {
            ##
            ##  Tag: dump location
            ##
    
            #   initialize new location buffer
            $BUFFER{$1} = [] if (not exists($BUFFER{$1}));
    
            #   insert location pointer into current location
            if ($BUFFER{$location} == $BUFFER{$1}) {
                warning($file, $line, "self-reference of location ``$location'' - ignoring");
            }
            else {
                push(@{$BUFFER{$location}}, $BUFFER{$1});
            }
        }
        elsif (   $remain =~ s|^\.\.(\!?[a-zA-Z][a-zA-Z0-9_]*\!?)>>||
               or $remain =~ s|^{#(\!?[a-zA-Z][a-zA-Z0-9_]*\!?)#:||) {
            ##
            ##  Tag: enter location
            ##
    
            #   remember old location on stack
            push(@LOCSTACK, $location);
    
            #   determine location and optional
            #   qualifies, then enter this location
            $location = $1;
            my $rewind_now  = 0;
            my $rewind_next = 0;
            if ($location =~ m|^\!(.*)$|) {
                #   location should be rewinded now
                $location = $1;
                $rewind_now = 1;
            }
            if ($location =~ m|^(.*)\!$|) {
                #   location should be rewinded next time
                $location = $1;
                $rewind_next = 1;
            }
    
            #   initialize location buffer
            $BUFFER{$location} = [] if (not exists($BUFFER{$location}));
    
            #   is a "rewind now" forced by a "rewind next" from last time?
            if ($OVRWRITE{$location}) {
                $rewind_now = 1;
                $OVRWRITE{$location} = 0;
            }
    
            #   remember a "rewind next" for next time
            $OVRWRITE{$location} = 1 if ($rewind_next);
    
            #   execute a "rewind now" by clearing the location buffer
            if ($rewind_now == 1) {
                while ($#{$BUFFER{$location}} > -1) {
                    shift(@{$BUFFER{$location}});
                }
            }
        }
        elsif (   $remain =~ s|^<<([a-zA-Z][a-zA-Z0-9_]*)?\.\.||
               or $remain =~ s|^:#([a-zA-Z][a-zA-Z0-9_]*)?#}||) {
            ##
            ##  Tag: leave location
            ##
    
            if ($#LOCSTACK == -1) {
                warning($file, $line, "already in ``null'' location -- ignoring leave");
            }
            else {
                my $loc = $1;
                if ($loc eq 'null') {
                    warning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, "cannot leave ull'' location -- ignoring leaarning($file, $line, 