###################################################
# C parser generator for IDL structures
# Copyright tridge@samba.org 2000
# released under the GNU GPL

package IdlParser;

use Data::Dumper;

my($res);

#####################################################################
# parse a properties list
sub ParseProperties($)
{
    my($props) = shift;
    foreach my $d (@{$props}) {
	if (ref($d) ne "HASH") {
	    $res .= "[$d] ";
	} else {
	    foreach my $k (keys %{$d}) {
		$res .= "[$k($d->{$k})] ";
	    }
	}
    }
}

#####################################################################
# parse a structure element
sub ParseElement($)
{
    my($element) = shift;
    (defined $element->{PROPERTIES}) && ParseProperties($element->{PROPERTIES});
    ParseType($element->{TYPE});
    $res .= " ";
    if ($element->{POINTERS}) {
	for (my($i)=0; $i < $element->{POINTERS}; $i++) {
	    $res .= "*";
	}
    }
    $res .= "$element->{NAME}";
    (defined $element->{ARRAY_LEN}) && ($res .= "[$element->{ARRAY_LEN}]");
}

#####################################################################
# parse a struct
sub ParseStruct($)
{
    my($struct) = shift;
    $res .= "struct {\n";
    if (defined $struct->{ELEMENTS}) {
	foreach my $e (@{$struct->{ELEMENTS}}) {
	    ParseElement($e);
	    $res .= ";\n";
	}
    }
    $res .= "}";
}


#####################################################################
# parse a union element
sub ParseUnionElement($)
{
    my($element) = shift;
    $res .= "[case($element->{CASE})] ";
    ParseElement($element->{DATA});
    $res .= ";\n";
}

#####################################################################
# parse a union
sub ParseUnion($)
{
    my($union) = shift;
    (defined $union->{PROPERTIES}) && ParseProperties($union->{PROPERTIES});
    $res .= "union {\n";
    foreach my $e (@{$union->{DATA}}) {
	ParseUnionElement($e);
    }
    $res .= "}";
}

#####################################################################
# parse a type
sub ParseType($)
{
    my($data) = shift;
    if (ref($data) eq "HASH") {
	($data->{TYPE} eq "STRUCT") &&
	    ParseStruct($data);
	($data->{TYPE} eq "UNION") &&
	    ParseUnion($data);
    } else {
	$res .= "$data";
    }
}

#####################################################################
# parse a typedef
sub ParseTypedef($)
{
    my($typedef) = shift;
    $res .= "typedef ";
    ParseType($typedef->{DATA});
    $res .= " $typedef->{NAME};\n\n";
}

#####################################################################
# parse a function
sub ParseFunction($)
{ 
    my($function) = shift;
    $res .= "/* ignoring function $function->{NAME} */\n";
}

#####################################################################
# parse the interface definitions
sub ParseInterface($)
{
    my($interface) = shift;
    my($data) = $interface->{DATA};
    foreach my $d (@{$data}) {
	($d->{TYPE} eq "TYPEDEF") &&
	    ParseTypedef($d);
	($d->{TYPE} eq "FUNCTION") && 
	    ParseFunction($d);
    }
}


#####################################################################
# parse a parsed IDL structure back into an IDL file
sub Parse($)
{
    my($idl) = shift;
    $res = "/* parser auto-generated by pidl */\n\n";
    foreach my $x (@{$idl}) {
	($x->{TYPE} eq "INTERFACE") && 
	    ParseInterface($x);
    }
    return $res;
}

1;
