#!/usr/bin/perl -s

if(!$ARGV[0]) {
    print <<MOO
Usage: genlang2 [-p=<prefix>][-t=<target>][-v] <language file>

<prefix>.h and <prefix>.c will be created in the current directory. <prefix>
is "lang" by default.

Use -v for verbose (debug) output.

MOO
;
    exit;
}

my $prefix = $p;
if(!$prefix) {
    $prefix="lang";
}
my $target = $t;
if(!$target) {
    print "Please specify a target!\n";
    exit;
}
my $verbose=$v;

my %id; # string to num hash
my @idnum; # num to string array

my %source; # id string to source phrase hash
my %dest; # id string to dest phrase hash
my %voice; # id string to voice phrase hash


my $input = $ARGV[0];

open(HFILE, ">$prefix.h");
open(CFILE, ">$prefix.c");

print HFILE <<MOO
/* This file was automatically generated using genlang2 */
/*
 * The str() macro/functions is how to access strings that might be
 * translated. Use it like str(MACRO) and expect a string to be
 * returned!
 */
#define str(x) language_strings[x]

/* this is the array for holding the string pointers.
   It will be initialized at runtime. */
extern unsigned char *language_strings[];
/* this contains the concatenation of all strings, separated by \\0 chars */
extern const unsigned char language_builtin[];

/* The enum below contains all available strings */
enum {
MOO
    ;

print CFILE <<MOO
/* This file was automaticly generated using genlang2, the strings come
   from "$input" */
   
#include "$prefix.h"

unsigned char *language_strings[LANG_LAST_INDEX_IN_ARRAY];
const unsigned char language_builtin[] =
MOO
    ;

my @m;
my $m="blank";

sub match {
    my ($string, $pattern)=@_;

    $pattern =~ s/\*/.?*/g;
    $pattern =~ s/\?/./g;

    return ($string =~ $pattern);
}

sub blank {
    # nothing to do
}

my %head;
sub header {
    my ($full, $n, $v)=@_;
    $head{$n}=$v;
}

my %phrase;
sub phrase {
    my ($full, $n, $v)=@_;
    $phrase{$n}=$v;
}

sub parsetarget {
    my ($debug, $strref, $full, $n, $v)=@_;
    my $string;
    my @all= split(" *, *", $n);
    my $test;
    for $test (@all) {
#        print "TEST ($debug) $target for $test\n";
        if(match($target, $test)) {
            $string = $v;
#            print "MATCH: $test => $v\n";
        }
    }
    if($string) {
        $$strref = $string;
    }
    return $string;
}

my $src;
sub source {
    parsetarget("src", \$src, @_);
}

my $dest;
sub dest {
    parsetarget("dest", \$dest, @_);
}

my $voice;
sub voice {
    parsetarget("voice", \$voice, @_);
}

my $idcount; # counter for ID numbers

open(LANG, "<$input");
while(<LANG>) {
    $line++;
    if($_ =~ / *\#/) {
        # comment
        next;
    }
    # get rid of DOS newlines
    $_ =~ s/\r//g;

   # print "M: $m\n";

    if(/ *<([^>]*)>/) {
        my $part = $1;
        #print "P: $part\n";
        if($part =~ /^\//) {
            if($part eq "/phrase") {
                my $idstr = $phrase{'id'};

                $id{$idstr} = $idcount;
                $idnum[$idcount]=$idstr;

                $source{$idstr}=$src;
                $dest{$idstr}=$dest;
                $voice{$idstr}=$voice;

                if($verbose) {
                    print "id: $phrase{id}\n";
                    print "source: $src\n";
                    print "dest: $dest\n";
                    print "voice: $voice\n";
                }

                $idcount++;

                undef $src;
                undef $dest;
                undef $voice;
                undef %phrase;
            }
            # starts with a slash, this _ends_ this section
            $m = pop @m; # get back old value
            next;
        }
        push @m, $m; # store old value
        $m = $1;
        next;
    }

    if(/^ *([^:]+): *(.*)/) {
        my ($name, $val)=($1, $2);
        &$m($_, $name, $val);
    }

}
close(LANG);

# Output the ID names for the enum in the header file
my $i;
for $i (1 .. $idcount) {
    my $name=$idnum[$i - 1]; # get the ID name

    $name =~ s/\"//g; # cut off the quotes

    printf HFILE ("    %s,\n", $name);
}

# Output separation marker for last string ID and the upcoming voice IDs

print HFILE <<MOO
    LANG_LAST_INDEX_IN_ARRAY, /* this is not a string, this is a marker */
    /* --- below this follows voice-only strings --- */
    VOICEONLY_DELIMITER = 0x8000,
MOO
    ;

# TODO: add voice-only phrase IDs here

# Output end of enum
print HFILE <<MOO
};
/* end of generated enum list */
MOO
    ;

# Output the target phrases for the source file
for $i (1 .. $idcount) {
    my $name=$idnum[$i - 1]; # get the ID
    my $dest = $dest{$name}; # get the destination phrase

    $dest =~ s:\"$:\\0\":; # insert a \0 before the second quote

    printf CFILE ("    %s\n", $dest);
}

# Output end of string chunk
print CFILE <<MOO
;
/* end of generated string list */
MOO
    ;

close(HFILE);
close(CFILE);

if($verbose) {
    printf("%d ID strings scanned\n", $idcount);

    print "* head *\n";
    for(keys %head) {
        printf "$_: %s\n", $head{$_};
    }
}

#print "* phrase *\n";
#for(keys %phrase) {
#    print "$_\n";
#}
