summaryrefslogtreecommitdiff
path: root/tools/pidl/lib/Parse/Pidl/Samba3/Header.pm
diff options
context:
space:
mode:
Diffstat (limited to 'tools/pidl/lib/Parse/Pidl/Samba3/Header.pm')
-rw-r--r--tools/pidl/lib/Parse/Pidl/Samba3/Header.pm217
1 files changed, 217 insertions, 0 deletions
diff --git a/tools/pidl/lib/Parse/Pidl/Samba3/Header.pm b/tools/pidl/lib/Parse/Pidl/Samba3/Header.pm
new file mode 100644
index 0000000000..78bd8fe339
--- /dev/null
+++ b/tools/pidl/lib/Parse/Pidl/Samba3/Header.pm
@@ -0,0 +1,217 @@
+###################################################
+# Samba3 NDR header generator for IDL structures
+# Copyright jelmer@samba.org 2005
+# released under the GNU GPL
+
+package Parse::Pidl::Samba3::Header;
+
+use strict;
+use Parse::Pidl::Typelist qw(hasType getType);
+use Parse::Pidl::Util qw(has_property ParseExpr);
+use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred);
+use Parse::Pidl::Samba3::Types qw(DeclShort);
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+my $res = "";
+my $tabs = "";
+sub indent() { $tabs.="\t"; }
+sub deindent() { $tabs = substr($tabs, 1); }
+sub pidl($) { $res .= $tabs.(shift)."\n"; }
+sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); }
+sub warning($$) { my ($e,$s) = @_; warn("$e->{FILE}:$e->{LINE}: $s\n"); }
+
+sub ParseElement($)
+{
+ my $e = shift;
+
+ foreach my $l (@{$e->{LEVELS}}) {
+ if ($l->{TYPE} eq "POINTER") {
+ return if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "top");
+ pidl "\tuint32 ptr$l->{POINTER_INDEX}_$e->{NAME};";
+ } elsif ($l->{TYPE} eq "SWITCH") {
+ pidl "\tuint32 level_$e->{NAME};";
+ } elsif ($l->{TYPE} eq "DATA") {
+ pidl "\t" . DeclShort($e) . ";";
+ } elsif ($l->{TYPE} eq "ARRAY") {
+ if ($l->{IS_CONFORMANT}) {
+ pidl "\tuint32 size_$e->{NAME};";
+ }
+ if ($l->{IS_VARYING}) {
+ pidl "\tuint32 length_$e->{NAME};";
+ pidl "\tuint32 offset_$e->{NAME};";
+ }
+ }
+ }
+}
+
+sub CreateStruct($$$$)
+{
+ my ($if,$fn,$n,$t) = @_;
+
+ pidl "typedef struct $n {";
+ ParseElement($_) foreach (@$t);
+
+ if (not @$t) {
+ # Some compilers don't like empty structs
+ pidl "\tuint32 dummy;";
+ }
+
+ pidl "} " . uc($n) . ";";
+ pidl "";
+}
+
+sub ParseFunction($$)
+{
+ my ($if,$fn) = @_;
+
+ my @in = ();
+ my @out = ();
+
+ foreach (@{$fn->{ELEMENTS}}) {
+ push (@in, $_) if (grep(/in/, @{$_->{DIRECTION}}));
+ push (@out, $_) if (grep(/out/, @{$_->{DIRECTION}}));
+ }
+
+ if (defined($fn->{RETURN_TYPE})) {
+ push (@out, {
+ NAME => "status",
+ TYPE => $fn->{RETURN_TYPE},
+ LEVELS => [
+ {
+ TYPE => "DATA",
+ DATA_TYPE => $fn->{RETURN_TYPE}
+ }
+ ]
+ } );
+ }
+
+ # define Q + R structures for functions
+
+ CreateStruct($if, $fn, "$if->{NAME}_q_$fn->{NAME}", \@in);
+ CreateStruct($if, $fn, "$if->{NAME}_r_$fn->{NAME}", \@out);
+}
+
+sub ParseStruct($$$)
+{
+ my ($if,$s,$n) = @_;
+
+ CreateStruct($if, $s, "$if->{NAME}_$n", $s->{ELEMENTS});
+}
+
+sub ParseUnion($$$)
+{
+ my ($if,$u,$n) = @_;
+
+ my $extra = {};
+
+ unless (has_property($u, "nodiscriminant")) {
+ $extra->{switch_value} = 1;
+ }
+
+ foreach my $e (@{$u->{ELEMENTS}}) {
+ foreach my $l (@{$e->{LEVELS}}) {
+ if ($l->{TYPE} eq "ARRAY") {
+ if ($l->{IS_CONFORMANT}) {
+ $extra->{"size"} = 1;
+ }
+ if ($l->{IS_VARYING}) {
+ $extra->{"length"} = $extra->{"offset"} = 1;
+ }
+ } elsif ($l->{TYPE} eq "POINTER") {
+ $extra->{"ptr$l->{POINTER_INDEX}"} = 1;
+ } elsif ($l->{TYPE} eq "SWITCH") {
+ $extra->{"level"} = 1;
+ }
+ }
+ }
+
+ pidl "typedef struct $if->{NAME}_$n\_ctr {";
+ indent;
+ pidl "uint32 $_;" foreach (keys %$extra);
+ pidl "union $if->{NAME}_$n {";
+ indent;
+ foreach (@{$u->{ELEMENTS}}) {
+ next if ($_->{TYPE} eq "EMPTY");
+ pidl "\t" . DeclShort($_) . ";";
+ }
+ deindent;
+ pidl "} u;";
+ deindent;
+ pidl "} ".uc("$if->{NAME}_$n\_ctr") .";";
+ pidl "";
+}
+
+sub ParseEnum($$$)
+{
+ my ($if,$s,$n) = @_;
+
+ pidl "typedef enum {";
+ pidl "$_," foreach (@{$s->{ELEMENTS}});
+ pidl "} $n;";
+}
+
+sub ParseBitmap($$$)
+{
+ my ($if,$s,$n) = @_;
+
+ pidl "#define $_" foreach (@{$s->{ELEMENTS}});
+}
+
+sub ParseInterface($)
+{
+ my $if = shift;
+
+ my $def = "_RPC_" . uc($if->{NAME}) . "_H";
+
+ pidl "";
+
+ pidl "\#ifndef $def";
+ pidl "\#define $def";
+
+ pidl "";
+
+ foreach (@{$if->{FUNCTIONS}}) {
+ pidl "\#define " . uc($_->{NAME}) . " $_->{OPNUM}" ;
+ }
+
+ pidl "";
+
+ foreach (@{$if->{TYPEDEFS}}) {
+ ParseStruct($if, $_->{DATA}, $_->{NAME}) if ($_->{DATA}->{TYPE} eq "STRUCT");
+ ParseEnum($if, $_->{DATA}, $_->{NAME}) if ($_->{DATA}->{TYPE} eq "ENUM");
+ ParseBitmap($if, $_->{DATA}, $_->{NAME}) if ($_->{DATA}->{TYPE} eq "BITMAP");
+ ParseUnion($if, $_->{DATA}, $_->{NAME}) if ($_->{DATA}->{TYPE} eq "UNION");
+ }
+
+ ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}});
+
+ foreach (@{$if->{CONSTS}}) {
+ pidl "$_->{NAME} ($_->{VALUE})";
+ }
+
+ pidl "\#endif /* $def */";
+}
+
+sub Parse($$)
+{
+ my($ndr,$filename) = @_;
+
+ $res = "";
+ $tabs = "";
+
+ pidl "/*";
+ pidl " * Unix SMB/CIFS implementation.";
+ pidl " * header auto-generated by pidl. DO NOT MODIFY!";
+ pidl " */";
+ pidl "";
+
+ # Loop over interfaces
+ foreach (@{$ndr}) {
+ ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
+ }
+ return $res;
+}
+
+1;