#!/usr/bin/perl -w

use strict;
use warnings;

open (PP,'pparam.h');
open (PARAMH,'>','proparam.h');
open (PARAMC,'>','proparam.c');
open (PARAMM1,'>','mono-wrapper/src/htp-c-opts.cs.inc');
open (PARAMM2,'>','mono-wrapper/src/htp-intset.cs.inc');
open (PARAMM3,'>','mono-wrapper/src/htp-intget.cs.inc');
open (PARAMM4,'>','mono-wrapper/src/htp-intprop.cs.inc');
open (PARAMDLLSYM,'>','htmltmplpro/src/libhtmltmplpro.sym');
open (PARAMDLLDEF,'>','htmltmplpro/src/libhtmltmplpro.def');

print PARAMDLLDEF "LIBRARY htmltmplpro\r\nEXPORTS\r\n";
{
    open my $fh, "<", 'htmltmplpro/src/libhtmltmplpro.sym.header' or die $!;
#    local $/; # enable localized slurp mode
#    my $content = <$fh>;
#    print PARAMDLLDEF $content;
#    close $fh;
    while (my $sym = <$fh>) {
	chomp $sym;
	print PARAMDLLDEF "   $sym\r\n";
	print PARAMDLLSYM "$sym\n";
    }
}

print PARAMH '
/*! \file proparam.h
    \brief Getters and setters for libhtmltmplpro options.

    Public interface to get and set libhtmltmplpro options.
 
    \author Igor Vlasenko <vlasenko@imath.kiev.ua>
    \warning This header file should never be included directly.
    Include <tmplpro.h> instead.
*/

/* generated; do not edit */
#ifndef _PROPARAM_H
#define _PROPARAM_H	1

struct tmplpro_param;

';
print PARAMC '/* generated; do not edit */
#include "pabidecl.h"
#include "pabstract.h"
#include "pparam.h"
#include "proparam.h"

';

print PARAMM1 '
    /* generated; do not edit */
    internal class C_OPTS {
';

print PARAMM2 '/* generated; do not edit */
';
print PARAMM3 '/* generated; do not edit */
';

#----------- BEGIN LOOP-------------------
while (<PP>) {
    last if m!/\*\s*private\s*\*/!;
    next if /^\s*\};\s*$/;
    next if /typedef/;
    next unless m!^\s*(.+);\s*(/\*.+\*/)?\s*$!;
    $_=$1;
    /(.*?)\s+(\S+)$/;
    my $type=$1;
    my $name=$2;
    my $flagtype=$type;
    $flagtype=~s/flag/int/;
    my $monotype=$flagtype;
    $monotype=~s/ABSTRACT_.*\*/IntPtr/;
    $monotype=~s/char\*\*/IntPtr/;
    $monotype=~s/const char\*/IntPtr/;
    $monotype=~s/char\*/IntPtr/;
    #$monotype=~s/struct exprval/exprval/;
    $monotype='C_API.'.$monotype if $monotype=~/(functype|PSTRING)/;

    if ($flagtype=~/functype$/) {
        print PARAMH "/*! \\fn $flagtype tmplpro_get_option_$name(struct tmplpro_param*);
    \\brief get address of callback of ::$flagtype
    \\param param -- pointer to an internal state.
*/
";
    } elsif ($flagtype=~/^ABSTRACT_/) {
        my $typeref=$flagtype;
        $typeref=~s/\*//;
        print PARAMH "/*! \\fn $flagtype tmplpro_get_option_$name(struct tmplpro_param*);
    \\brief get value of an external pointer that will be passed to a callback. see ::$typeref.
    \\param param -- pointer to an internal state.
*/
";
    } else {
        print PARAMH "/*! \\fn $flagtype tmplpro_get_option_$name(struct tmplpro_param*);
    \\brief get value of $name option.

    see HTML::Template::Pro perl module documentation for $name option.

    \\param param -- pointer to an internal state.
*/
";
    }
    print PARAMH "TMPLPRO_API $flagtype APICALL tmplpro_get_option_$name(struct tmplpro_param*);

";
    if ($flagtype=~/functype$/) {
        print PARAMH "/*! \\fn void tmplpro_set_option_$name(struct tmplpro_param*,$flagtype);
    \\brief set callback of ::$flagtype
    \\param param -- pointer to an internal state.
    \\param val -- callback address to set.
*/
";
    } elsif ($flagtype=~/^ABSTRACT_/) {
        my $typeref=$flagtype;
        $typeref=~s/\*//;
        print PARAMH "/*! \\fn void tmplpro_set_option_$name(struct tmplpro_param*,$flagtype);
    \\brief set external pointer that will be passed to a callback. see ::$typeref.
    \\param param -- pointer to an internal state.
    \\param val -- value to set.
*/
";
    } else {
        print PARAMH "/*! \\fn void tmplpro_set_option_$name(struct tmplpro_param*,$flagtype);
    \\brief set value of $name option.

    see HTML::Template::Pro perl module documentation for $name option.

    \\param param -- pointer to an internal state.
    \\param val -- value to set.
*/
";
    }
    print PARAMH "TMPLPRO_API void APICALL tmplpro_set_option_$name(struct tmplpro_param*,$flagtype);

";

    print PARAMC "
API_IMPL 
$flagtype 
APICALL tmplpro_get_option_$name(struct tmplpro_param* param) {
    return ".($type eq 'flag' ? '(int) ':'')."param->$name;
}

API_IMPL 
void
APICALL tmplpro_set_option_$name(struct tmplpro_param* param, $flagtype val) {
    param->$name=".($type eq 'flag' ? '(flag)':'')."val;
}
";
    print PARAMM1 "
    [DllImport(DLL.HTP_DLL, CallingConvention=DLL.HTP_CallingConvention, CharSet=DLL.HTPCharSet)]
      internal static extern $monotype tmplpro_get_option_$name(IntPtr c_param);

    [DllImport(DLL.HTP_DLL, CallingConvention=DLL.HTP_CallingConvention, CharSet=DLL.HTPCharSet)]
      internal static extern void tmplpro_set_option_$name(IntPtr c_param, $monotype val);
";
    print PARAMM2 '      case "'.$name.'": '."\t".'C_OPTS.tmplpro_set_option_'.$name.'(_c_param, val); break;
' if $monotype eq 'int';
    print PARAMM3 '      case "'.$name.'": '."\t".'return C_OPTS.tmplpro_get_option_'.$name.'(_c_param);
' if $monotype eq 'int';

    print PARAMM4 '
    /// <summary>
    /// HTML::Template::Pro template processing option.
    /// see HTML::Template::Pro perl module documentation for '.$name.' option.
    /// </summary>
    public int '.$name.' {
      get {
	return C_OPTS.tmplpro_get_option_'.$name.'(_c_param);
      }
      set {
	C_OPTS.tmplpro_set_option_'.$name.'(_c_param, value);
      }
    }
' if $monotype eq 'int';

    print PARAMDLLDEF "   tmplpro_get_option_$name\r\n";
    print PARAMDLLDEF "   tmplpro_set_option_$name\r\n";

    print PARAMDLLSYM "tmplpro_get_option_$name\n";
    print PARAMDLLSYM "tmplpro_set_option_$name\n";
}
#----------- END LOOP-------------------

print PARAMH '
#endif /* proparam.h */
';

print PARAMM1 '
    }
';


close (PARAMH);
close (PARAMC);
close (PARAMM1);
close (PARAMM2);
close (PARAMM3);
close (PARAMM4);
close (PARAMDLLDEF);
