r8806: Move data representation-independent data into seperate header
[sfrench/samba-autobuild/.git] / source4 / build / pidl / Parse / Pidl / Samba / EJS.pm
index 72f280add039f79c8f5511c21c4eb32df7f9b6df..5cd7b462aee1584582657e374020005f444e2604 100644 (file)
@@ -8,6 +8,7 @@ package Parse::Pidl::Samba::EJS;
 
 use strict;
 use Parse::Pidl::Typelist;
+use Parse::Pidl::Util qw(has_property);
 
 my($res);
 my %constants;
@@ -110,7 +111,7 @@ sub fn_prefix($)
 {
        my $fn = shift;
 
-       return "" if (Parse::Pidl::Util::has_property($fn, "public"));
+       return "" if (has_property($fn, "public"));
        return "static ";
 }
 
@@ -120,13 +121,14 @@ sub EjsPullScalar($$$$$)
 {
        my ($e, $l, $var, $name, $env) = @_;
 
-       return if (Parse::Pidl::Util::has_property($e, "value"));
+       return if (has_property($e, "value"));
 
-       $var = get_pointer_to($var);
-       # have to handle strings specially :(
-       if ($e->{TYPE} eq "string") {
-               $var = get_pointer_to($var);
-       }
+        my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
+        $var = get_pointer_to($var);
+        # have to handle strings specially :(
+        if ($e->{TYPE} eq "string" && $pl && $pl->{TYPE} eq "POINTER") {
+                $var = get_pointer_to($var);
+        }
        pidl "NDR_CHECK(ejs_pull_$e->{TYPE}(ejs, v, $name, $var));";
 }
 
@@ -202,7 +204,7 @@ sub EjsPullSwitch($$$$$)
 sub EjsPullElement($$$$$)
 {
        my ($e, $l, $var, $name, $env) = @_;
-       if (Parse::Pidl::Util::has_property($e, "charset")) {
+       if (has_property($e, "charset")) {
                EjsPullString($e, $l, $var, $name, $env);
        } elsif ($l->{TYPE} eq "ARRAY") {
                EjsPullArray($e, $l, $var, $name, $env);
@@ -287,12 +289,31 @@ sub EjsUnionPull($$)
        pidl "}";
 }
 
+##############################################
+# put the enum elements in the constants array
+sub EjsEnumConstant($)
+{
+       my $d = shift;
+       my $v = 0;
+       foreach my $e (@{$d->{ELEMENTS}}) {
+               my $el = $e;
+               chomp $el;
+               if ($el =~ /^(.*)=\s*(.*)\s*$/) {
+                       $el = $1;
+                       $v = $2;
+               }
+               $constants{$el} = $v;
+               $v++;
+       }
+}
+
 ###########################
 # pull a enum
 sub EjsEnumPull($$)
 {
        my $name = shift;
        my $d = shift;
+       EjsEnumConstant($d);
        pidl fn_prefix($d);
        pidl "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, enum $name *r)\n{";
        indent;
@@ -326,7 +347,7 @@ sub EjsBitmapPull($$)
 sub EjsTypedefPull($)
 {
        my $d = shift;
-       return if (Parse::Pidl::Util::has_property($d, "noejs"));
+       return if (has_property($d, "noejs"));
        if ($d->{DATA}->{TYPE} eq 'STRUCT') {
                EjsStructPull($d->{NAME}, $d->{DATA});
        } elsif ($d->{DATA}->{TYPE} eq 'UNION') {
@@ -369,7 +390,11 @@ sub EjsPullFunction($)
 sub EjsPushScalar($$$$$)
 {
        my ($e, $l, $var, $name, $env) = @_;
-       $var = get_pointer_to($var);
+        # have to handle strings specially :(
+        my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
+        if ($e->{TYPE} ne "string" || ($pl && $pl->{TYPE} eq "POINTER")) {
+                $var = get_pointer_to($var);
+        }
        pidl "NDR_CHECK(ejs_push_$e->{TYPE}(ejs, v, $name, $var));";
 }
 
@@ -439,7 +464,7 @@ sub EjsPushArray($$$$$)
 sub EjsPushElement($$$$$)
 {
        my ($e, $l, $var, $name, $env) = @_;
-       if (Parse::Pidl::Util::has_property($e, "charset")) {
+       if (has_property($e, "charset")) {
                EjsPushString($e, $l, $var, $name, $env);
        } elsif ($l->{TYPE} eq "ARRAY") {
                EjsPushArray($e, $l, $var, $name, $env);
@@ -530,18 +555,7 @@ sub EjsEnumPush($$)
 {
        my $name = shift;
        my $d = shift;
-       my $v = 0;
-       # put the enum elements in the constants array
-       foreach my $e (@{$d->{ELEMENTS}}) {
-               my $el = $e;
-               chomp $el;
-               if ($el =~ /^(.*)=\s*(.*)\s*$/) {
-                       $el = $1;
-                       $v = $2;
-               }
-               $constants{$el} = $v;
-               $v++;
-       }
+       EjsEnumConstant($d);
        pidl fn_prefix($d);
        pidl "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const enum $name *r)\n{";
        indent;
@@ -582,7 +596,7 @@ sub EjsBitmapPush($$)
 sub EjsTypedefPush($)
 {
        my $d = shift;
-       return if (Parse::Pidl::Util::has_property($d, "noejs"));
+       return if (has_property($d, "noejs"));
        if ($d->{DATA}->{TYPE} eq 'STRUCT') {
                EjsStructPush($d->{NAME}, $d->{DATA});
        } elsif ($d->{DATA}->{TYPE} eq 'UNION') {
@@ -622,15 +636,18 @@ sub EjsPushFunction($)
 
 #################################
 # generate a ejs mapping function
-sub EjsFunction($)
+sub EjsFunction($$)
 {
        my $d = shift;
+       my $iface = shift;
        my $name = $d->{NAME};
+       my $callnum = uc("DCERPC_$name");
+       my $table = "&dcerpc_table_$iface";
 
        pidl "static int ejs_$name(int eid, int argc, struct MprVar **argv)";
        pidl "{";
        indent;
-       pidl "return ejs_rpc_call(eid, argc, argv, \"$name\", (ejs_pull_function_t)ejs_pull_$name, (ejs_push_function_t)ejs_push_$name);";
+       pidl "return ejs_rpc_call(eid, argc, argv, $table, $callnum, (ejs_pull_function_t)ejs_pull_$name, (ejs_push_function_t)ejs_push_$name);";
        deindent;
        pidl "}\n";
 }
@@ -645,17 +662,17 @@ sub EjsConst($)
 
 #####################################################################
 # parse the interface definitions
-sub EjsInterface($)
+sub EjsInterface($$)
 {
-       my($interface) = shift;
+       my($interface,$needed) = @_;
        my @fns = ();
        my $name = $interface->{NAME};
 
        %constants = ();
 
        foreach my $d (@{$interface->{TYPEDEFS}}) {
-               EjsTypedefPush($d);
-               EjsTypedefPull($d);
+               ($needed->{"push_$d->{NAME}"}) && EjsTypedefPush($d);
+               ($needed->{"pull_$d->{NAME}"}) && EjsTypedefPull($d);
        }
 
        foreach my $d (@{$interface->{FUNCTIONS}}) {
@@ -663,7 +680,7 @@ sub EjsInterface($)
                
                EjsPullFunction($d);
                EjsPushFunction($d);
-               EjsFunction($d);
+               EjsFunction($d, $name);
 
                push (@fns, $d->{NAME});
        }
@@ -672,33 +689,29 @@ sub EjsInterface($)
                EjsConst($d);
        }
 
-       pidl "void setup_ejs_$name(void)";
+       pidl "static int ejs_$name\_init(int eid, int argc, struct MprVar **argv)";
        pidl "{";
        indent;
+       pidl "struct MprVar *obj = mprInitObject(eid, \"$name\", argc, argv);";
        foreach (@fns) {
-               pidl "ejsDefineCFunction(-1, \"dcerpc_$_\", ejs_$_, NULL, MPR_VAR_SCRIPT_HANDLE);";
+               pidl "mprSetCFunction(obj, \"$_\", ejs_$_);";
        }
-       deindent;
-       pidl "}\n";
-
-       pidl "void setup_ejs_constants_$name(int eid)";
-       pidl "{";
-       indent;
        foreach my $v (keys %constants) {
                my $value = $constants{$v};
                if (substr($value, 0, 1) eq "\"") {
-                       pidl "ejs_set_constant_string(eid, \"$v\", $value);";
+                       pidl "mprSetVar(obj, \"$v\", mprString($value));";
                } else {
-                       pidl "ejs_set_constant_int(eid, \"$v\", $value);";
+                       pidl "mprSetVar(obj, \"$v\", mprCreateNumberVar($value));";
                }
        }
+       pidl "return 0;";
        deindent;
        pidl "}\n";
 
        pidl "NTSTATUS ejs_init_$name(void)";
        pidl "{";
        indent;
-       pidl "return smbcalls_register_ejs(\"$name\", setup_ejs_$name, setup_ejs_constants_$name);";
+       pidl "return smbcalls_register_ejs(\"$name\_init\", ejs_$name\_init);";
        deindent;
        pidl "}";
 }
@@ -715,20 +728,75 @@ sub Parse($$)
     pidl "
 /* EJS wrapper functions auto-generated by pidl */
 #include \"includes.h\"
-#include \"lib/ejs/ejs.h\"
+#include \"lib/appweb/ejs/ejs.h\"
 #include \"scripting/ejs/ejsrpc.h\"
+#include \"scripting/ejs/smbcalls.h\"
 #include \"librpc/gen_ndr/ndr_misc_ejs.h\"
 #include \"$hdr\"
 #include \"$ejs_hdr\"
 
 ";
+
+    my %needed = ();
+
+    foreach my $x (@{$ndr}) {
+           ($x->{TYPE} eq "INTERFACE") && NeededInterface($x, \%needed);
+    }
+
     foreach my $x (@{$ndr}) {
-           if ($x->{TYPE} eq "INTERFACE") {
-                   ($x->{TYPE} eq "INTERFACE") && EjsInterface($x);
-           }
+           ($x->{TYPE} eq "INTERFACE") && EjsInterface($x, \%needed);
     }
 
     return $res;
 }
 
+sub NeededFunction($$)
+{
+       my ($fn,$needed) = @_;
+       $needed->{"pull_$fn->{NAME}"} = 1;
+       $needed->{"push_$fn->{NAME}"} = 1;
+       foreach my $e (@{$fn->{ELEMENTS}}) {
+               if (grep (/in/, @{$e->{DIRECTION}})) {
+                       $needed->{"pull_$e->{TYPE}"} = 1;
+               }
+               if (grep (/out/, @{$e->{DIRECTION}})) {
+                       $needed->{"push_$e->{TYPE}"} = 1;
+               }
+       }
+}
+
+sub NeededTypedef($$)
+{
+       my ($t,$needed) = @_;
+       if (Parse::Pidl::Util::has_property($t, "public")) {
+               $needed->{"pull_$t->{NAME}"} = not Parse::Pidl::Util::has_property($t, "noejs");
+               $needed->{"push_$t->{NAME}"} = not Parse::Pidl::Util::has_property($t, "noejs");
+       }
+       if ($t->{DATA}->{TYPE} ne "STRUCT" && 
+           $t->{DATA}->{TYPE} ne "UNION") {
+               return;
+       }
+       for my $e (@{$t->{DATA}->{ELEMENTS}}) {
+               if ($needed->{"pull_$t->{NAME}"}) {
+                       $needed->{"pull_$e->{TYPE}"} = 1;
+               }
+               if ($needed->{"push_$t->{NAME}"}) {
+                       $needed->{"push_$e->{TYPE}"} = 1;
+               }
+       }
+}
+
+#####################################################################
+# work out what parse functions are needed
+sub NeededInterface($$)
+{
+       my ($interface,$needed) = @_;
+       foreach my $d (@{$interface->{FUNCTIONS}}) {
+           NeededFunction($d, $needed);
+       }
+       foreach my $d (reverse @{$interface->{TYPEDEFS}}) {
+           NeededTypedef($d, $needed);
+       }
+}
+
 1;