summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2005-03-30 11:15:51 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:11:20 -0500
commit79fb22f9d4a02bfaca8b915ede865cfe6da0e51c (patch)
tree5ca8651fee6585b3409a9d35acc4debca1151e73
parent0403e2032b258d25f6ff744029c3a0327cebda5a (diff)
downloadsamba-79fb22f9d4a02bfaca8b915ede865cfe6da0e51c.tar.gz
samba-79fb22f9d4a02bfaca8b915ede865cfe6da0e51c.tar.bz2
samba-79fb22f9d4a02bfaca8b915ede865cfe6da0e51c.zip
r6130: More work on the NDR tree generator
(This used to be commit ad7ea50eb29402d213438e5fcaa56f853c00487e)
-rw-r--r--source4/build/pidl/ndr.pm261
1 files changed, 260 insertions, 1 deletions
diff --git a/source4/build/pidl/ndr.pm b/source4/build/pidl/ndr.pm
index e668dbb39d..f7b52dd83d 100644
--- a/source4/build/pidl/ndr.pm
+++ b/source4/build/pidl/ndr.pm
@@ -20,7 +20,7 @@ sub GetElementLevelTable($)
my $order = [];
my $is_deferred = 0;
-
+
# First, all the pointers
foreach my $i (1..need_wire_pointer($e)) {
push (@$order, {
@@ -182,6 +182,29 @@ sub array_type($)
return undef;
}
+#####################################################################
+# work out the correct alignment for a structure or union
+sub find_largest_alignment($)
+{
+ my $s = shift;
+
+ my $align = 1;
+ for my $e (@{$s->{ELEMENTS}}) {
+ my $a = 1;
+
+ if (Ndr::need_wire_pointer($e)) {
+ $a = 4;
+ } else {
+ $a = align_type($e->{TYPE});
+ }
+
+ $align = $a if ($align < $a);
+ }
+
+ return $align;
+}
+
+
# determine if an element needs a reference pointer on the wire
# in its NDR representation
sub need_wire_pointer($)
@@ -202,4 +225,240 @@ sub need_wire_pointer($)
return $n;
}
+sub ParseElement($)
+{
+ my $e = shift;
+
+ return {
+ NAME => $e->{NAME},
+ PROPERTIES => $e->{PROPERTIES},
+ LEVELS => GetElementLevelTable($e)
+ };
+}
+
+sub ParseStruct($)
+{
+ my $e = shift;
+ my @elements = ();
+
+ foreach my $x (@{$e->{ELEMENTS}})
+ {
+ push @elements, ParseElement($x);
+ }
+
+ return {
+ TYPE => "STRUCT",
+ ELEMENTS => \@elements,
+ PROPERTIES => $e->{PROPERTIES}
+ };
+}
+
+sub ParseUnion($)
+{
+ my $e = shift;
+ my @elements = ();
+
+ foreach my $x (@{$e->{ELEMENTS}})
+ {
+ my $t;
+ if ($x->{TYPE} eq "EMPTY") {
+ $t = { TYPE => "EMPTY" };
+ } else {
+ $t = ParseElement($x);
+ if (util::has_property($t, "default")) {
+ $t->{DEFAULT} = "default";
+ } else {
+ $t->{CASE} = $t->{PROPERTIES}->{CASE};
+ }
+ }
+ push @elements, $t;
+ }
+
+ return {
+ TYPE => "UNION",
+ ELEMENTS => \@elements,
+ PROPERTIES => $e->{PROPERTIES}
+ };
+}
+
+sub ParseEnum($)
+{
+ my $e = shift;
+
+ return {
+ TYPE => "ENUM",
+ ELEMENTS => $e->{ELEMENTS},
+ PROPERTIES => $e->{PROPERTIES}
+ };
+}
+
+sub ParseBitmap($)
+{
+ my $e = shift;
+
+ return {
+ TYPE => "BITMAP",
+ ELEMENTS => $e->{ELEMENTS},
+ PROPERTIES => $e->{PROPERTIES}
+ };
+}
+
+sub ParseTypedef($$)
+{
+ my $ndr = shift;
+ my $d = shift;
+ my $data;
+
+ if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
+ CheckPointerTypes($d->{DATA}, $ndr->{PROPERTIES}->{pointer_default});
+ }
+
+ if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
+ $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
+ }
+
+ if ($d->{DATA}->{TYPE} eq "STRUCT") {
+ $data = ParseStruct($d->{DATA});
+ } elsif ($d->{DATA}->{TYPE} eq "UNION") {
+ $data = ParseUnion($d->{DATA});
+ } elsif ($d->{DATA}->{TYPE} eq "ENUM") {
+ $data = ParseEnum($d->{DATA});
+ } elsif ($d->{DATA}->{TYPE} eq "BITMAP") {
+ $data = ParseBitmap($d->{DATA});
+ } else {
+ die("Unknown data type '$d->{DATA}->{TYPE}'");
+ }
+
+ return {
+ TYPE => "TYPEDEF",
+ PROPERTIES => $d->{PROPERTIES},
+ DATA => $data
+ };
+}
+
+sub ParseFunction($$)
+{
+ my $ndr = shift;
+ my $d = shift;
+ my @in = ();
+ my @out = ();
+
+ CheckPointerTypes($d,
+ $ndr->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref"
+ );
+
+ foreach my $x ($d->{ELEMENTS}) {
+ if (util::has_property($x, "in")) {
+ push @in, ParseElement($x);
+ }
+ if (util::has_property($x, "out")) {
+ push @out, ParseElement($x);
+ }
+ }
+
+ return {
+ TYPE => "FUNCTION",
+ RETURN_TYPE => $d->{RETURN_TYPE},
+ PROPERTIES => $d->{PROPERTIES},
+ ELEMENTS => {
+ IN => \@in,
+ OUT => \@out
+ }
+ };
+}
+
+sub CheckPointerTypes($$)
+{
+ my $s = shift;
+ my $default = shift;
+
+ foreach my $e (@{$s->{ELEMENTS}}) {
+ if ($e->{POINTERS}) {
+ if (not defined(Ndr::pointer_type($e))) {
+ $e->{PROPERTIES}->{$default} = 1;
+ }
+
+ if (Ndr::pointer_type($e) eq "ptr") {
+ print "Warning: ptr is not supported by pidl yet\n";
+ }
+ }
+ }
+}
+
+sub ParseInterface($)
+{
+ my $idl = shift;
+ my @functions = ();
+ my @typedefs = ();
+ my $version;
+
+ if (not util::has_property($idl, "pointer_default")) {
+ # MIDL defaults to "ptr" in DCE compatible mode (/osf)
+ # and "unique" in Microsoft Extensions mode (default)
+ $idl->{PROPERTIES}->{pointer_default} = "unique";
+ }
+
+ foreach my $d (@{$idl->{DATA}}) {
+ if ($d->{TYPE} eq "DECLARE" or $d->{TYPE} eq "TYPEDEF") {
+ push (@typedefs, ParseTypedef($idl, $d));
+ }
+
+ if ($d->{TYPE} eq "FUNCTION") {
+ push (@functions, ParseFunction($idl, $d));
+ }
+ }
+
+ $version = "0.0";
+
+ if(defined $idl->{PROPERTIES}->{version}) {
+ $version = $idl->{PROPERTIES}->{version};
+ }
+
+
+ return {
+ NAME => $idl->{NAME},
+ UUID => util::has_property($idl, "uuid"),
+ VERSION => $version,
+ TYPE => "INTERFACE",
+ PROPERTIES => $idl->{PROPERTIES},
+ FUNCTIONS => \@functions,
+ TYPEDEFS => \@typedefs
+ };
+}
+
+# Convert a IDL tree to a NDR tree
+# Gives a result tree describing all that's necessary for easily generating
+# NDR parsers
+# - list of interfaces
+# - list with functions
+# - list with in elements
+# - list with out elements
+# - list of typedefs
+# - list with structs
+# - alignment of structure
+# - list with elements
+# - list with unions
+# - alignment of union
+# - list with elements
+# - list with enums
+# - base type
+# - list with bitmaps
+# - base type
+# per element:
+# - alignment
+# - "level" table
+# properties are saved
+# pointer types explicitly specified
+sub Parse($)
+{
+ my $idl = shift;
+ my @ndr = ();
+
+ foreach my $x (@{$idl}) {
+ push @ndr, ParseInterface($x);
+ }
+
+ return \@ndr;
+}
+
1;