#!/usr/bin/perl

use strict;
use Getopt::Std;

my $increment;
my %opts;
my $file;
my $format;
my $commentstr;

sub Convert {

    open (APIc, $file); 
    
    my $iparmkey  = "^[ \t]*([ID]PARM_[0-9A-Z_]*)[ \t]*= ([0-9]*),?";
    my $iparmkey2 = "^[ \t]*([ID]PARM_SIZE)[ \t]*= ([0-9]*),?";
    my $comment = "";
    my $chaine; 
    foreach my $line (<APIc> )
    {
	$chaine = $line;
	if (!($comment eq $commentstr) &&
	    $line =~ /\/\*(.*)/)
	{
	    $comment = $commentstr;
	    $chaine  = $1;
	}
	if ($comment eq $commentstr &&
	    $line =~ /(.*)\*\//)
	{
	    $comment = "";
	    $chaine  = $1;
	}
	if ($comment eq $commentstr)
	{
	    print $comment.$chaine;
	}
	if ($line =~ /$iparmkey/)
	{
	    if ($line =~ /$iparmkey2/)
	    {
		$chaine = sprintf($format, $1, ($2));
	    }
	    else
	    {
		$chaine = sprintf($format, $1, ($2+$increment));
	    }
	    print $comment.$chaine;
	}
	else
	{
	    if ($line =~ /^[ \t]*([0-9A-Z_]*)[ \t]*=[ \t]*([0-9]*),?/)
	    {
		$chaine = sprintf($format, $1, $2);
		print $comment.$chaine
	    }
	    else
	    {
		if ($line =~ /[ ]*#define[ ]*([0-9A-Z_]*)[ \t]*([0-9]*)/)
		{
		    if ( (!($1 =~ /MTX\_IS/)) && (!($1 =~ /API\_H/)) )
		    {
			$chaine = sprintf($format, $1, $2);
			
			print $comment.$chaine;
		    }
		}
		else 
		{
		   if (($line =~ /\_POS\_/) || ($line =~ /Matrix\ type/))
		   {
		       #print "!- ".$1."\n" if (/^\/\**(.*)\*\//);
		       print "\n" if (/^[ ]*$/);
		   }
		}
	    }

	}
	
    }
    close APIc;
}

sub Usage {

    print "APIc2f.pl -f api.h\n";
    print "  convertit le fichier api.h en un header pour le fortran.\n";
    print "   -h   Affiche cette aide\n";
    print "   -m   If using with murge\n";
    print "   -p   If using with pascal\n";
}


getopts("hmf:p",\%opts);

if ( defined $opts{h} || !(defined $opts{f})){
    Usage();
    exit;
}
$commentstr = "! ";
if (defined $opts{m}){
    $increment = 1;
    $format    = "INTEGER(KIND=MURGE_INTS_KIND), PARAMETER :: %-30s = %d\n";
}
else 
{
    if (defined $opts{p}) {
	$increment = 0;
	print "unit pastix;\n";
	print "interface\n";
	print "\n";
	print "uses S_recc_ksc ;\n";
	print "\n";
	print "pastix_complex=record\n";
	print "  re,im:Single;\n";
	print "end;\n";
	print "\n";
	print "pastix_dcomplex=record\n";
	print "  re,im:Double;\n";
	print "end;\n";
	print "\n";
	print "const\n";
	print "\n";

	$format = "  %-30s = %d;\n";
	$commentstr = "// ";
    }
    else
    {
	$increment = 1;
	$format    = "#define %-30s INT(%d , KIND=PASTIX_INT_KIND)\n";
    }
}

$file = $opts{f};

Convert();

if (defined $opts{p}) {
    my %types = ("s" => "Single",
                 "d" => "Double",
                 "c" => "pastix_complexe",
		 "z" => "pastix_dcomplexe");
    foreach my $key ( sort keys %types) {
	printf "procedure %s_pastix(pastix_data: Pointer;\n", $key;
	printf "                   mpi_comm: Integer;\n";
	printf "                   n: Integer;\n";
	printf "                   colptr: TArray<Integer>;\n";
	printf "                   rows: TArray<Integer>;\n";
	printf "                   values: TArray<%s>;\n", $types{$key};
	printf "                   perm: TArray<Integer>;\n";
	printf "                   invp: TArray<Integer>;\n";
	printf "                   rhs: TArray<%s>;\n", $types{$key};
	printf "                   nrhs: Integer;\n";
	printf "                   iparm: TArray<Integer>;\n";
	printf "                   dparm: TArray<Double>); cdecl;\n";
	printf "         external 'libpastix';\n";
	printf "\n";
	printf "procedure %s_pastix_checkMatrix( pastix_comm : Integer;\n", $key;
	printf "                                verb : Integer;\n";
	printf "                                flagsym : Integer;\n";
	printf "                                flagcorg : Integer;\n";
	printf "                                n : Integer;\n";
	printf "                                colptr : pointer;\n";
	printf "                                row : pointer;\n";
	printf "                                avals : pointer;\n";
	printf "                                loc2glob : pointer;\n";
	printf "                                dof : Integer); cdecl;\n";
	printf "         external 'libpastix';\n";
	printf "\n";
	printf "function %s_pastix_checkMatrix_2steps( data_check: pointer;\n", $key;
	printf "                                      pastix_comm: integer;\n";
	printf "                                      verb : integer;\n";
	printf "                                      flagsym : integer;\n";
	printf "                                      flagcor : integer;\n";
	printf "                                      n : integer ;\n";
	printf "                                      colptr : TArray<Integer> ;\n";
	printf "                                      row : TArray<integer> ;\n";
	printf "                                      avals : TArray<complexe> ;\n";
	printf "                                      loc2glob : pointer ;\n";
	printf "                                      dof : integer) : integer ; cdecl ;\n";
	printf "         external 'libpastix';\n";
	printf "\n";
	printf "procedure %s_pastix_checkmatrix_2steps_end (data_check : pointer ;\n", $key;
	printf "                                          verb : integer ;\n";
	printf "                                          row : TArray<integer> ;\n";
	printf "                                          avals : TArray<complexe> ;\n";
	printf "                                          dof : integer) ; cdecl ;\n";
	printf "          external 'libpastix';\n";
	printf "\n";
	printf "implementation\n";
	printf "\n";
	printf "end.\n";
    }
}
