#!perl
#
# This mkheader script makes two C header files,
# $FmH_File and $ToH_File (see below their values).
# These files are used to build Lingua::AR::MacArabic.
#
use 5.006001;
use strict;
use warnings;

my $MapFile = "arabic.map";
my $AddFile = "addition.map";
my $EncName = "macar";

###################

my $TypeBC = 'STDCHAR'; # byte string
my $TypeWC = 'U16';     # Unicode codepoint
my $TypeDC = 'STDCHAR'; # direction

my $FmH_File = "fm${EncName}.h";
my $ToH_File = "to${EncName}.h";

my $DirNt = 0;
my $DirLR = 1;
my $DirRL = 2;
my $UvPDF = 0x202C;
my $UvLRO = 0x202D;
my $UvRLO = 0x202E;

###################

my (%FmMac, %ToMacR, %ToMacL, %ToMacN, %Direct);

for my $f ($AddFile, $MapFile) {
    open IN, "<$f" or die "$f $!";
    binmode IN;

    while (<IN>) {
	next if /^#/;
	next if /^\s*$/;

	my @t = split;
	my $e = hex $t[0];
	next if ! $t[1];

	die "ill-formed column 2"
	    unless $t[1] =~ /(?:<(RL|LR)>\+)?(0x[0-9A-Fa-f]+)/;

	my $d = $1 || '';
	my $u = hex $2;

	die "$e > 255" if $e > 255;

	$FmMac {$e} = $u;
	$Direct{$e} = $d eq 'LR' ? $DirLR : $d eq 'RL' ? $DirRL : $DirNt;

	my($a,$b) = unpack('CC', pack 'n', $u);
	$ToMacL{$a}{$b} = $e if $d ne 'RL'; # L or neutral
	$ToMacR{$a}{$b} = $e if $d ne 'LR'; # R or neutral
	$ToMacN{$a}{$b} = $e if $d eq '';   # neutral
    }
    close IN or die "$f can't be closed.\n";
}

###################

open FM, ">$FmH_File" or die "$FmH_File $!" or die;
binmode FM;

print FM <<"EOH";
#define MACBIDI_DIR_NT	($DirNt)
#define MACBIDI_DIR_LR	($DirLR)
#define MACBIDI_DIR_RL	($DirRL)

#define MACBIDI_UV_PDF	($UvPDF)
#define MACBIDI_UV_LRO	($UvLRO)
#define MACBIDI_UV_RLO	($UvRLO)
\n
EOH

print FM "$TypeWC fm_${EncName}_tbl [256] = {\n";
for (my $i = 0; $i < 256; $i++) {
    printf FM "\t%d", defined $FmMac{$i} ? $FmMac{$i} : 0;
    print  FM ','  if $i != 255;
    print  FM "\n" if $i % 8 == 7;
}
print FM "};\n\n";

print FM "$TypeDC fm_${EncName}_dir [256] = {\n";
for (my $i = 0; $i < 256; $i++) {
    printf FM " %d", defined $Direct{$i} ? $Direct{$i} : $DirNt;
    print  FM ','  if $i != 255;
    print  FM "\n" if $i % 16 == 15;
}
print FM "};\n\n";

close FM or die "$FmH_File can't be closed.\n";

###################

open TO, ">$ToH_File" or die "$ToH_File $!" or die;
binmode TO;

my %ToMacHsh = (
    L => \%ToMacL,
    R => \%ToMacR,
    N => \%ToMacN,
);

foreach my $dir (qw( L R N ) ) {
    my $hsh = $ToMacHsh{$dir};
    my $typ = $TypeBC;

    foreach my $le (sort { $a <=> $b } keys %$hsh) {
	print TO "$typ to_${EncName}_${le}_${dir} [256] = {\n";
	for (my $i = 0; $i < 256; $i++) {
	    printf TO "\t%s",
		defined $hsh->{$le}{$i} ? "($typ) $hsh->{$le}{$i}" : 0;
	    print  TO ','  if $i != 255;
	    print  TO "\n" if $i % 8 == 7;
	}
	print TO "};\n\n";
    }

    print TO "$typ* to_${EncName}_${dir} [] = {\n";
    for (my $i = 0; $i < 256; $i++) {
	print TO "\t",
	    defined $hsh->{$i} ? "to_${EncName}_${i}_${dir}" : "NULL";
	print TO ','  if $i != 255;
	print TO "\n" if $i % 8 == 7;
    }
    print TO "};\n\n\n";
}

close TO or die "$ToH_File can't be closed.\n";

1;
__END__