summaryrefslogtreecommitdiff
path: root/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm
diff options
context:
space:
mode:
Diffstat (limited to 'source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm')
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm269
1 files changed, 269 insertions, 0 deletions
diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm
new file mode 100644
index 0000000000..8518537ddb
--- /dev/null
+++ b/source4/pidl/lib/Parse/Pidl/Samba3/Parser.pm
@@ -0,0 +1,269 @@
+###################################################
+# Samba3 NDR parser generator for IDL structures
+# Copyright jelmer@samba.org 2005
+# released under the GNU GPL
+
+package Parse::Pidl::Samba3::Parser;
+
+use strict;
+use Parse::Pidl::Typelist qw(hasType getType mapType);
+use Parse::Pidl::Util qw(has_property ParseExpr);
+use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred);
+use Parse::Pidl::Samba3::Util qw(MapSamba3Type);
+
+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 ParseElementLevelData($$$$$)
+{
+ my ($e,$l,$nl,$env,$varname) = @_;
+
+ #FIXME: This only works for scalar types
+ pidl "if (!prs_$l->{DATA_TYPE}(\"$e->{NAME}\", ps, depth, &$varname))";
+ pidl "\treturn False;";
+ pidl "";
+}
+
+sub ParseElementLevelArray($$$$$)
+{
+ my ($e,$l,$nl,$env,$varname) = @_;
+
+ #FIXME
+ pidl "for (i=0; i<".ParseExpr("length_$e->{NAME}", $env) .";i++) {";
+ indent;
+ ParseElementLevel($e,$nl,$env,"$varname\[i]");
+ deindent;
+ pidl "}";
+}
+
+sub ParseElementLevelSwitch($$$$$)
+{
+ my ($e,$l,$nl,$env,$varname) = @_;
+
+ pidl "if (!prs_uint32(\"level\", ps, depth, " . ParseExpr("level_$e->{NAME}", $env) . ", ps, depth))";
+ pidl "\treturn False;";
+ pidl "";
+
+ ParseElementLevel($e,$nl,$env,$varname);
+}
+
+sub ParseElementLevelPtr($$$$$)
+{
+ my ($e,$l,$nl,$env,$varname) = @_;
+
+ # No top-level ref pointers for Samba 3
+ return if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP");
+
+ pidl "if (!prs_uint32(\"ptr_$e->{NAME}\",ps,depth,&" . ParseExpr("ptr_$e->{NAME}", $env) . ", ps, depth))";
+ pidl "\treturn False;";
+ pidl "";
+
+ pidl "if (" . ParseExpr("ptr_$e->{NAME}", $env) . ") {";
+ indent;
+ ParseElementLevel($e,$nl,$env,$varname);
+ deindent;
+ pidl "}";
+}
+
+sub ParseElementLevelSubcontext($$$$$)
+{
+ my ($e,$l,$nl,$env,$varname) = @_;
+
+ fatal($e, "subcontext() not supported for Samba 3");
+}
+
+sub ParseElementLevel($$$$)
+{
+ my ($e,$l,$env,$varname) = @_;
+
+ {
+ DATA => \&ParseElementLevelData,
+ SUBCONTEXT => \&ParseElementLevelSubcontext,
+ POINTER => \&ParseElementLevelPtr,
+ SWITCH => \&ParseElementLevelSwitch,
+ ARRAY => \&ParseElementLevelArray
+ }->{$l->{TYPE}}->($e,$l,GetNextLevel($e,$l),$env,$varname);
+}
+
+sub ParseElement($$)
+{
+ my ($e,$env) = @_;
+
+ ParseElementLevel($e, $e->{LEVELS}[0], $env, ParseExpr($e->{NAME}, $env));
+}
+
+sub CreateStruct($$$)
+{
+ my ($fn,$s,$es) = @_;
+
+ my $args = "";
+ foreach my $e (@$es) {
+ $args .= ", " . MapSamba3Type($_);
+ }
+
+ pidl "BOOL init_$fn($s *v$args)";
+ pidl "{";
+ indent;
+ pidl "DEBUG(5,(\"init_$fn\\n\"));";
+ # Call init for all arguments
+ foreach my $e (@$es) {
+ foreach my $l (@{$e->{LEVELS}}) {
+ #FIXME
+ }
+ }
+ pidl "return True;";
+ deindent;
+ pidl "}";
+ pidl "";
+
+ pidl "BOOL $fn(const char *desc, $s *v, prs_struct *ps, int depth)";
+ pidl "{";
+ indent;
+ pidl "if (v == NULL)";
+ pidl "\treturn False;";
+ pidl "";
+ pidl "prs_debug(ps, depth, desc, \"$fn\");";
+ pidl "depth++;";
+ pidl "if (!prs_align(ps))";
+ pidl "\treturn False;";
+ pidl "";
+
+ my $env = {};
+ foreach my $e (@$es) {
+ foreach my $l (@{$e->{LEVELS}}) {
+ if ($l->{TYPE} eq "DATA") {
+ $env->{"$e->{NAME}"} = $e->{"v->$e->{NAME}"};
+ } elsif ($l->{TYPE} eq "POINTER") {
+ $env->{"ptr_$e->{NAME}"} = $e->{"v->ptr_$e->{NAME}"};
+ } elsif ($l->{TYPE} eq "SWITCH") {
+ $env->{"level_$e->{NAME}"} = $e->{"v->level_$e->{NAME}"};
+ }
+ }
+ }
+
+ ParseElement($_, $env) foreach (@$es);
+
+ pidl "return True;";
+ deindent;
+ pidl "}";
+ pidl "";
+}
+
+sub ParseStruct($$$)
+{
+ my ($if,$s,$n) = @_;
+
+ my $fn = "$if->{NAME}_io_$n";
+ my $sn = uc("$if->{NAME}_$n");
+
+ CreateStruct($fn, $sn, $s->{ELEMENTS});
+}
+
+sub ParseUnion($$$)
+{
+ my ($if,$u,$n) = @_;
+
+ my $fn = "$if->{NAME}_io_$n";
+ my $sn = uc("$if->{NAME}_$n");
+
+ pidl "BOOL $fn(const char *desc, $sn* v, uint32 level, prs_struct *ps, int depth)";
+ pidl "{";
+ indent;
+ pidl "switch (level) {";
+ indent;
+
+ foreach (@{$u->{ELEMENTS}}) {
+ pidl "$_->{CASE}:";
+ indent;
+ pidl "depth++;";
+ ParseElement($_, {});
+ deindent;
+ pidl "depth--;";
+ pidl "break";
+ }
+
+ deindent;
+ pidl "}";
+ pidl "";
+ pidl "return True;";
+ deindent;
+ 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}
+ }
+ ]
+ } );
+ }
+
+ CreateStruct("$if->{NAME}_io_q_$fn->{NAME}", uc("$if->{NAME}_q_$fn->{NAME}"), \@in);
+ CreateStruct("$if->{NAME}_io_r_$fn->{NAME}", uc("$if->{NAME}_r_$fn->{NAME}"), \@out);
+}
+
+sub ParseInterface($)
+{
+ my $if = shift;
+
+ # Structures first
+ pidl "/* $if->{NAME} structures */";
+ foreach (@{$if->{TYPEDEFS}}) {
+ ParseStruct($if, $_->{DATA}, $_->{NAME}) if ($_->{TYPE} eq "STRUCT");
+ ParseUnion($if, $_->{DATA}, $_->{NAME}) if ($_->{TYPE} eq "UNION");
+ }
+
+ pidl "/* $if->{NAME} functions */";
+ ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}});
+}
+
+sub Parse($$)
+{
+ my($ndr,$filename) = @_;
+
+ $tabs = "";
+ $res = "";
+
+ pidl "/*";
+ pidl " * Unix SMB/CIFS implementation.";
+ pidl " * parser auto-generated by pidl. DO NOT MODIFY!";
+ pidl " */";
+ pidl "";
+ pidl "#include \"includes.h\"";
+ pidl "";
+ pidl "#undef DBGC_CLASS";
+ pidl "#define DBGC_CLASS DBGC_RPC_PARSE";
+ pidl "";
+
+ foreach (@$ndr) {
+ ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
+ }
+
+ return $res;
+}
+
+1;