1
0
mirror of https://github.com/samba-team/samba.git synced 2025-11-18 00:23:50 +03:00
Files
samba-mirror/source/build/pidl/eparser.pm

299 lines
6.6 KiB
Perl

###################################################
# parser generator for IDL structures
# Copyright tpot@samba.org 2001
# Copyright tridge@samba.org 2000
# released under the GNU GPL
package eparser;
use strict;
my($res);
sub has_property($$)
{
my($props) = shift;
my($p) = shift;
foreach my $d (@{$props}) {
if (ref($d) ne "HASH") {
return 1, if ($d eq $p);
return 1, if ($d eq "in,out" && ($p eq "in" || $p eq "out"));
} else {
foreach my $k (keys %{$d}) {
return $d->{$k}, if ($k eq $p);
}
}
}
return 0;
}
#####################################################################
# 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 an array - called in buffers context
sub ParseArray($)
{
my($elt) = shift;
$res .= "\tfor (i = 0; i < count; i++) {\n";
if (util::is_scalar_type($elt)) {
$res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, NULL, \"$elt->{NAME});\n";
$res .= "\t}\n\n";
} else {
$res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, \"PARSE_SCALARS\", \"$elt->{NAME}\");\n";
$res .= "\t}\n\n";
$res .= "\tfor (i = 0; i < count; i++) {\n";
$res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, \"PARSE_BUFFERS\", \"$elt->{NAME}\");\n";
$res .= "\t}\n\n";
}
}
#####################################################################
# parse a structure element
sub ParseElement($$)
{
my($elt) = shift;
my($flags) = shift;
# Arg is a policy handle
if (util::has_property($elt, "context_handle")) {
$res .= "\toffset = prs_policy_hnd(tvb, offset, pinfo, tree);\n";
return;
}
# Parse type
if ($flags =~ /scalars/) {
# Pointers are scalars
if ($elt->{POINTERS}) {
$res .= "\t\toffset = prs_ptr(tvb, offset, pinfo, tree, &ptr_$elt->{NAME}, \"$elt->{NAME}\");\n";
} else {
# Simple type are scalars too
if (util::is_scalar_type($elt->{TYPE})) {
$res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, NULL, \"$elt->{NAME}\");\n\n";
}
}
}
if ($flags =~ /buffers/) {
# Scalars are not buffers, except if they are pointed to
if (!util::is_scalar_type($elt->{TYPE}) || $elt->{POINTERS}) {
# If we have a pointer, check it
if ($elt->{POINTERS}) {
$res .= "\t\tif (ptr_$elt->{NAME})\n\t";
}
if (util::has_property($elt, "size_is")) {
ParseArray($elt);
} else {
$res .= "\t\toffset = prs_$elt->{TYPE}(tvb, offset, pinfo, tree, ";
if (util::is_scalar_type($elt->{TYPE})) {
$res .= "NULL, ";
} else {
$res .= "flags, ";
}
$res .= "\"$elt->{NAME}\");\n\n";
}
}
}
return;
}
#####################################################################
# parse a struct
sub ParseStruct($)
{
my($struct) = shift;
if (defined $struct->{ELEMENTS}) {
# Parse scalars
$res .= "\tif (flags & PARSE_SCALARS) {\n";
foreach my $e (@{$struct->{ELEMENTS}}) {
ParseElement($e, "scalars");
}
$res .= "\t}\n\n";
# Parse buffers
$res .= "\tif (flags & PARSE_BUFFERS) {\n";
foreach my $e (@{$struct->{ELEMENTS}}) {
ParseElement($e, "buffers");
}
$res .= "\t}\n\n";
}
}
#####################################################################
# parse a union element
sub ParseUnionElement($)
{
my($element) = shift;
$res .= "\tcase $element->{DATA}->{NAME}: \n";
$res .= "\t\toffset = prs_$element->{DATA}->{TYPE}(tvb, offset, pinfo, tree, \"$element->{DATA}->{NAME}\");\n\t\tbreak;\n";
}
#####################################################################
# parse a union
sub ParseUnion($)
{
my($union) = shift;
$res .= "\tswitch (level) {\n";
(defined $union->{PROPERTIES}) && ParseProperties($union->{PROPERTIES});
foreach my $e (@{$union->{DATA}}) {
ParseUnionElement($e);
}
$res .= "\t}\n";
}
#####################################################################
# 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 .= "static int prs_$typedef->{NAME}(tvbuff_t *tvb, int offset,\
\tpacket_info *pinfo, proto_tree *tree, int flags, char *name)\n{\n";
ParseType($typedef->{DATA});
$res .= "\treturn offset;\n";
$res .= "}\n\n";
}
#####################################################################
# parse a function
sub ParseFunctionArg($$)
{
my($arg) = shift;
my($io) = shift; # "in" or "out"
if (util::has_property($arg, $io)) {
# For some reason, pointers to elements in function definitions
# aren't parsed.
if (defined($arg->{POINTERS}) && !util::is_scalar_type($arg->{TYPE})) {
$arg->{POINTERS} -= 1, if ($arg->{POINTERS} > 0);
delete($arg->{POINTERS}), if ($arg->{POINTERS} == 0);
}
ParseElement($arg, "scalars|buffers");
}
}
#####################################################################
# parse a function
sub ParseFunction($)
{
my($function) = shift;
# Input function
$res .= "static int $function->{NAME}_q(tvbuff_t *tvb, int offset,\
\tpacket_info *pinfo, proto_tree *tree, char *drep)\n{\n";
foreach my $arg (@{$function->{DATA}}) {
ParseFunctionArg($arg, "in");
}
$res .= "\n\treturn offset;\n}\n\n";
# Output function
$res .= "static int $function->{NAME}_r(tvbuff_t *tvb, int offset,\
\tpacket_info *pinfo, proto_tree *tree, char *drep)\n{\n";
foreach my $arg (@{$function->{DATA}}) {
ParseFunctionArg($arg, "out");
}
$res .= "\n\toffset = prs_ntstatus(tvb, offset, pinfo, tree);\n";
$res .= "\n\treturn offset;\n}\n\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;