#!/usr/bin/perl

use File::Temp qw/ :mktemp  /;

sub usage {

print <<EOM;

Usage: fa_build_gc [OPTIONS]

This program builds GC WRE rules.

  --in=<input-rules> - specifies the file name of input WRE rules,
    gc.rules.txt is used if omited

  --tagset=<input-file> - reads input tagset from the <input-file>,
    is not used by default

  --dict-root=<path> - specifies dictionary path, if not specified the
    dictionary path is taken from the \$DICTS_ROOT environment variable

  --tagset2=<input-file> - if this parameter is specified then all WRE
    references are resolved by the tag-dictionary and corresponding digitizer
    will be constructed, not used by default

  --ldb=<ldb-dump> - specifies PRM LDB file, it is needed for tag-dictionary
    digitizer, not used by default

  --out-pref=<dir> - adds this prefix to all output files

  --input-enc=<enc> - input encoding, "UTF-8" - is used by default

  --verbose - prints additional information during the compilation
EOM

}


#
# *** Process command line parameters ***
#

$in_rules = "gc.rules.txt" ;
$tagset = "" ;
$tagset2 = "" ;
$ldb = "" ;
$input_enc = "--input-enc=UTF-8" ;
$pref = "";
$verbose = "" ;
$dumps = "" ;
$confs = "" ;

while (0 < 1 + $#ARGV) {

    if("--help" eq $ARGV [0]) {

        usage ();
        exit (0);

    } elsif ($ARGV [0] =~ /^--input-enc=./) {

        $input_enc = $ARGV [0];

    } elsif ($ARGV [0] =~ /^--in=(.+)/) {

        $in_rules = $1;

    } elsif ($ARGV [0] =~ /^--tagset=(.+)/) {

        $tagset = $ARGV [0];

    } elsif ($ARGV [0] =~ /^--dict-root=(.+)/) {

        $ENV{'DICTS_ROOT'} = $1;

    } elsif ($ARGV [0] =~ /^--tagset2=(.+)/) {

        $tagset2 = $ARGV [0];

    } elsif ($ARGV [0] =~ /^--ldb=(.+)/) {

        $ldb = $ARGV [0];

    } elsif ($ARGV [0] =~ /^--out-pref=(.+)/) {

        $pref = $1;

    } elsif ("--verbose" eq $ARGV [0]) {

        $verbose = "--verbose";

    } elsif ($ARGV [0] =~ /^-.*/) {

        print STDERR "ERROR: Unknown parameter $$ARGV[0], see fa_build_gc --help";
        exit (1);

    } else {

        last;
    }
    shift @ARGV;
}

($fh, $ext_dig) = mkstemp ("fa_build_gc_XXXXX");
close $fh;


#
# Build common Moore machine
#

$command = "".
 "fa_build_wre --type=moore $tagset $tagset2 $ldb $input_enc --build-dump --in=$in_rules --out=$pref.common.dump --out3=$pref.acts.cxx --out-ext=$ext_dig" ;

`$command` ;


if (-s "$pref.common.dump") {
  $dumps = "$pref.common.dump" ;
} else {
  print STDERR "ERROR: Cannot build common Moore automaton\n" ;
  exit 1;
}

if ($verbose eq "--verbose") {
  print STDERR "\nfa_build_gc\tCommon Moore machine has been built.\n" ;
}


#
# Compile each rule as a Mealy automaton separatelly
#

$command = "fa_preproc --cpp-out=$pref.acts.cxx < $in_rules | " ;
open INPUT, $command ;

open CONF, ">$pref.conf" ;
print CONF "[wre]\n" ; 

$rule = "";
$num = 0;

while(<INPUT>) {

    s/[\r\n]+//g;

    if($_ eq "") {

      if($rule eq "") {
        print STDERR "\nfa_build_gc\tERROR: Internal error, the rule $num is empty.\n" ;
        exit 1;
      }

      ($fh, $tmprule) = mkstemp ("fa_build_gc_XXXXX");
      close $fh;

      open RULE, ">$tmprule" ;
      print RULE $rule ; 
      close RULE;

      $numstr = sprintf("%03d", $num);

      $command2 = "fa_build_wre --no-preproc --build-dump --type=mealy --no-trivial $tagset $tagset2 $ldb $input_enc --in-ext=$ext_dig --in=$tmprule --out=$pref.$numstr.dump" ;

      # execute the command
      `$command2` ;

      if (-e $tmprule) {
        unlink $tmprule ;
      }

      if(-s "$pref.$numstr.dump") {
         $dumps .= " $pref.$numstr.dump" ;
         print CONF "fsm-count 1\n" ;
      } else {
         print CONF "fsm-count 0\n" ;
      }

      if ($verbose eq "--verbose") {
        print STDERR "\nfa_build_gc\tRule $num has been built.\n" ;
      }

      $rule = "";
      $num++;

    } else {

      $rule .= "$_\n" ;
    }
}

close INPUT ;
close CONF;


#
# build configuration
#

`fa_build_conf --in=$pref.conf --out=$pref.conf.map.txt` ;
`fa_fsm2fsm_pack --alg=triv --type=mmap --auto-test --in=$pref.conf.map.txt --out=$pref.conf.map.dump` ;


#
# merge dumps
#

`fa_merge_dumps --out=$pref.dump $pref.conf.map.dump $dumps` ;


#
# Remove temporary files
#

END {
    if (-e $ext_dig) {
      unlink $ext_dig ;
    }
    if (-e $tmprule) {
      unlink $tmprule ;
    }
}
