summaryrefslogtreecommitdiff
path: root/source4/build/pidl
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-07-07 06:23:36 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:19:18 -0500
commit93aba2c0871a0991dceba2a580d4b04f196adec3 (patch)
tree608ebf28580bd878c68f47d92e9680f80301c80f /source4/build/pidl
parent824f5b47818fd4cc7fe0084bf454bb31930c4f38 (diff)
downloadsamba-93aba2c0871a0991dceba2a580d4b04f196adec3.tar.gz
samba-93aba2c0871a0991dceba2a580d4b04f196adec3.tar.bz2
samba-93aba2c0871a0991dceba2a580d4b04f196adec3.zip
r8191: updated the ejs code generator in pidl to generate enough code for
simple rpc calls to work. Still very rough, but its a start. (This used to be commit fb2639bbc203e49f6719922b6850edf28c8748a1)
Diffstat (limited to 'source4/build/pidl')
-rw-r--r--source4/build/pidl/ejs.pm355
-rwxr-xr-xsource4/build/pidl/pidl.pl5
2 files changed, 340 insertions, 20 deletions
diff --git a/source4/build/pidl/ejs.pm b/source4/build/pidl/ejs.pm
index 57ede8de64..14c0c3668f 100644
--- a/source4/build/pidl/ejs.pm
+++ b/source4/build/pidl/ejs.pm
@@ -1,6 +1,7 @@
###################################################
# EJS function wrapper generator
# Copyright jelmer@samba.org 2005
+# Copyright Andrew Tridgell 2005
# released under the GNU GPL
package EjsClient;
@@ -15,35 +16,353 @@ sub pidl ($)
$res .= shift;
}
-sub EJSFunction($)
+# this should probably be in ndr.pm
+sub GenerateStructEnv($)
+{
+ my $x = shift;
+ my %env;
+
+ foreach my $e (@{$x->{ELEMENTS}}) {
+ $env{$e->{NAME}} = "r->$e->{NAME}";
+ }
+
+ $env{"this"} = "r";
+
+ return \%env;
+}
+
+sub GenerateFunctionInEnv($)
+{
+ my $fn = shift;
+ my %env;
+
+ foreach my $e (@{$fn->{ELEMENTS}}) {
+ if (grep (/in/, @{$e->{DIRECTION}})) {
+ $env{$e->{NAME}} = "r->in.$e->{NAME}";
+ }
+ }
+
+ return \%env;
+}
+
+sub GenerateFunctionOutEnv($)
+{
+ my $fn = shift;
+ my %env;
+
+ foreach my $e (@{$fn->{ELEMENTS}}) {
+ if (grep (/out/, @{$e->{DIRECTION}})) {
+ $env{$e->{NAME}} = "r->out.$e->{NAME}";
+ } elsif (grep (/in/, @{$e->{DIRECTION}})) {
+ $env{$e->{NAME}} = "r->in.$e->{NAME}";
+ }
+ }
+
+ return \%env;
+}
+
+sub get_pointer_to($)
+{
+ my $var_name = shift;
+
+ if ($var_name =~ /^\*(.*)$/) {
+ return $1;
+ } elsif ($var_name =~ /^\&(.*)$/) {
+ return "&($var_name)";
+ } else {
+ return "&$var_name";
+ }
+}
+
+sub get_value_of($)
+{
+ my $var_name = shift;
+
+ if ($var_name =~ /^\&(.*)$/) {
+ return $1;
+ } else {
+ return "*$var_name";
+ }
+}
+
+
+###########################
+# pull a scalar element
+sub EjsPullScalar($$)
+{
+ my $e = shift;
+ my $env = shift;
+ my $var = util::ParseExpr($e->{NAME}, $env);
+ my $ptr = get_pointer_to($var);
+ pidl "\tNDR_CHECK(ejs_pull_$e->{TYPE}(ejs, v, \"$e->{NAME}\", $ptr));\n";
+}
+
+
+###########################
+# pull an arrar element
+# only handles a very limited range of array types so far
+sub EjsPullArray($$$)
+{
+ my $e = shift;
+ my $l = shift;
+ my $env = shift;
+ my $length = util::ParseExpr($l->{LENGTH_IS}, $env);
+ my $var = util::ParseExpr($e->{NAME}, $env);
+ my $ptr = get_pointer_to($var);
+ pidl "\tNDR_CHECK(ejs_pull_array(ejs, v, \"$e->{NAME}\", $length, sizeof($ptr\[0]), (void **)$ptr, (ejs_pull_t)ejs_pull_$e->{TYPE}));\n";
+}
+
+###########################
+# pull a structure element
+sub EjsPullElement($$)
+{
+ my $e = shift;
+ my $env = shift;
+ my $l = $e->{LEVELS}[0];
+ ($l->{TYPE} eq "ARRAY") && EjsPullArray($e, $l, $env);
+ ($l->{TYPE} eq "DATA") && EjsPullScalar($e, $env);
+}
+
+###########################
+# pull a struct
+sub EjsStructPull($$)
+{
+ my $name = shift;
+ my $d = shift;
+ my $env = GenerateStructEnv($d);
+ pidl "\nstatic NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, struct $name *r)\n{\n";
+ pidl "\tNDR_CHECK(ejs_pull_struct_start(ejs, &v, name));\n";
+ foreach my $e (@{$d->{ELEMENTS}}) {
+ EjsPullElement($e, $env);
+ }
+ pidl "\treturn NT_STATUS_OK;\n";
+ pidl "}\n\n";
+}
+
+###########################
+# pull a enum
+sub EjsEnumPull($$)
+{
+ my $name = shift;
+ my $d = shift;
+ pidl "\nstatic NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, enum $name *r)\n{\n";
+ pidl "\tunsigned e;\n";
+ pidl "\tNDR_CHECK(ejs_pull_enum(ejs, v, name, &e));\n";
+ pidl "\t*r = e;\n";
+ pidl "\treturn NT_STATUS_OK;\n";
+ pidl "}\n\n";
+}
+
+
+###########################
+# generate a structure pull
+sub EjsTypedefPull($)
+{
+ my $d = shift;
+ $d->{DATA}->{TYPE} eq 'STRUCT' && EjsStructPull($d->{NAME}, $d->{DATA});
+ $d->{DATA}->{TYPE} eq 'ENUM' && EjsEnumPull($d->{NAME}, $d->{DATA});
+}
+
+#####################
+# generate a function
+sub EjsPullFunction($)
{
my $d = shift;
+ my $env = GenerateFunctionInEnv($d);
- pidl "static int ejs_$d->{NAME}(struct EspRequest *ep, int argc, struct MprVar **argv)\n";
+ pidl "\nstatic NTSTATUS ejs_pull_$d->{NAME}(struct ejs_rpc *ejs, struct MprVar *v, struct $d->{NAME} *r)\n";
pidl "{\n";
- # FIXME
+ pidl "\tNDR_CHECK(ejs_pull_struct_start(ejs, &v, \"in\"));\n";
+
+ foreach my $e (@{$d->{ELEMENTS}}) {
+ next unless (grep(/in/, @{$e->{DIRECTION}}));
+ EjsPullElement($e, $env);
+ }
- pidl "\treturn 0;\n";
+ pidl "\treturn NT_STATUS_OK;\n";
+ pidl "}\n\n";
+}
+
+
+###########################
+# pull a scalar element
+sub EjsPushScalar($$$)
+{
+ my $e = shift;
+ my $l = shift;
+ my $env = shift;
+ my $var = util::ParseExpr($e->{NAME}, $env);
+
+ if (not typelist::is_scalar($l->{DATA_TYPE}) or
+ typelist::scalar_is_reference($l->{DATA_TYPE})) {
+ $var = get_pointer_to($var);
+ }
+
+ pidl "\tNDR_CHECK(ejs_push_$e->{TYPE}(ejs, v, \"$e->{NAME}\", $var));\n";
+}
+
+###########################
+# pull a pointer element
+sub EjsPushPointer($$$)
+{
+ my $e = shift;
+ my $l = shift;
+ my $env = shift;
+ my $var = util::ParseExpr($e->{NAME}, $env);
+
+ while ($l->{TYPE} eq "POINTER") {
+ $var = get_value_of($var);
+ $l = Ndr::GetNextLevel($e, $l);
+ }
+ if (not typelist::is_scalar($l->{DATA_TYPE})) {
+ $var = get_pointer_to($var);
+ }
+
+ pidl "\tNDR_CHECK(ejs_push_$e->{TYPE}(ejs, v, \"$e->{NAME}\", $var));\n";
+}
+
+
+###########################
+# push an arrar element
+# only handles a very limited range of array types so far
+sub EjsPushArray($$$)
+{
+ my $e = shift;
+ my $l = shift;
+ my $env = shift;
+ my $length = util::ParseExpr($l->{LENGTH_IS}, $env);
+ my $var = util::ParseExpr($e->{NAME}, $env);
+ pidl "\tNDR_CHECK(ejs_push_array(ejs, v, \"$e->{NAME}\", $length, sizeof($var\[0]), (void *)$var, (ejs_push_t)ejs_push_$e->{TYPE}));\n";
+}
+
+###########################
+# push a structure element
+sub EjsPushElement($$)
+{
+ my $e = shift;
+ my $env = shift;
+ my $l = $e->{LEVELS}[0];
+ ($l->{TYPE} eq "ARRAY") && EjsPushArray($e, $l, $env);
+ ($l->{TYPE} eq "DATA") && EjsPushScalar($e, $l, $env);
+ ($l->{TYPE} eq "POINTER") && EjsPushPointer($e, $l, $env);
+}
+
+###########################
+# push a struct
+sub EjsStructPush($$)
+{
+ my $name = shift;
+ my $d = shift;
+ my $env = GenerateStructEnv($d);
+ pidl "\nstatic NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, struct $name *r)\n{\n";
+ pidl "\tNDR_CHECK(ejs_push_struct_start(ejs, &v, name));\n";
+ foreach my $e (@{$d->{ELEMENTS}}) {
+ EjsPushElement($e, $env);
+ }
+ pidl "\treturn NT_STATUS_OK;\n";
+ pidl "}\n\n";
+}
+
+###########################
+# push a union
+sub EjsUnionPush($$)
+{
+ my $name = shift;
+ my $d = shift;
+ pidl "\nstatic NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, union $name *r)\n{\n";
+ pidl "\treturn NT_STATUS_OK;\n";
+ pidl "}\n\n";
+}
+
+###########################
+# push a enum
+sub EjsEnumPush($$)
+{
+ my $name = shift;
+ my $d = shift;
+ pidl "\nstatic NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, enum $name r)\n{\n";
+ pidl "\tNDR_CHECK(ejs_push_enum(ejs, v, name, r));\n";
+ pidl "\treturn NT_STATUS_OK;\n";
+ pidl "}\n\n";
+}
+
+
+###########################
+# generate a structure push
+sub EjsTypedefPush($)
+{
+ my $d = shift;
+ $d->{DATA}->{TYPE} eq 'STRUCT' && EjsStructPush($d->{NAME}, $d->{DATA});
+ $d->{DATA}->{TYPE} eq 'UNION' && EjsUnionPush($d->{NAME}, $d->{DATA});
+ $d->{DATA}->{TYPE} eq 'ENUM' && EjsEnumPush($d->{NAME}, $d->{DATA});
+}
+
+
+#####################
+# generate a function
+sub EjsPushFunction($)
+{
+ my $d = shift;
+ my $env = GenerateFunctionOutEnv($d);
+
+ pidl "\nstatic NTSTATUS ejs_push_$d->{NAME}(struct ejs_rpc *ejs, struct MprVar *v, const struct $d->{NAME} *r)\n";
+ pidl "{\n";
+
+ pidl "\tNDR_CHECK(ejs_push_struct_start(ejs, &v, \"out\"));\n";
+
+ foreach my $e (@{$d->{ELEMENTS}}) {
+ next unless (grep(/out/, @{$e->{DIRECTION}}));
+ EjsPushElement($e, $env);
+ }
+
+ pidl "\treturn NT_STATUS_OK;\n";
+ pidl "}\n\n";
+}
+
+
+#################################
+# generate a ejs mapping function
+sub EjsFunction($)
+{
+ my $d = shift;
+ my $name = $d->{NAME};
+
+ pidl "static int ejs_$name(int eid, int argc, struct MprVar **argv)\n";
+ pidl "{\n";
+ pidl "\treturn ejs_rpc_call(eid, argc, argv, \"$name\", (ejs_pull_function_t)ejs_pull_$name, (ejs_push_function_t)ejs_push_$name);\n";
pidl "}\n\n";
}
#####################################################################
# parse the interface definitions
-sub EJSInterface($)
+sub EjsInterface($)
{
my($interface) = shift;
my @fns = ();
+ my $name = $interface->{NAME};
+
+ foreach my $d (@{$interface->{TYPEDEFS}}) {
+ EjsTypedefPush($d);
+ EjsTypedefPull($d);
+ }
foreach my $d (@{$interface->{FUNCTIONS}}) {
next if not defined($d->{OPNUM});
- EJSFunction($d);
+ EjsPullFunction($d);
+ EjsPushFunction($d);
+ EjsFunction($d);
push (@fns, $d->{NAME});
}
-
- return @fns;
+
+ pidl "void setup_ejs_$name(void)\n";
+ pidl "{\n";
+ foreach (@fns) {
+ pidl "\tejsDefineCFunction(-1, \"dcerpc_$_\", ejs_$_, NULL, MPR_VAR_SCRIPT_HANDLE);\n";
+ }
+ pidl "}\n";
}
#####################################################################
@@ -51,24 +370,22 @@ sub EJSInterface($)
sub Parse($$)
{
my($ndr,$hdr) = @_;
- my @fns = ();
$res = "";
- pidl "#include \"$hdr\"\n\n";
- pidl "/* EJS wrapper functions auto-generated by pidl */\n\n";
+ pidl "
+/* EJS wrapper functions auto-generated by pidl */
+#include \"includes.h\"
+#include \"lib/ejs/ejs.h\"
+#include \"$hdr\"
+#include \"scripting/ejs/ejsrpc.h\"
+
+";
foreach my $x (@{$ndr}) {
if ($x->{TYPE} eq "INTERFACE") {
- push (@fns, EJSInterface($x));
+ ($x->{TYPE} eq "INTERFACE") && EjsInterface($x);
}
}
- pidl "void setup_ejs_functions(void)\n";
- pidl "{\n";
- foreach (@fns) {
- pidl "\tespDefineCFunction(NULL, \"$_\", esp_$_, NULL);\n";
- }
- pidl "}\n";
-
return $res;
}
diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl
index 198a946625..daf404d38f 100755
--- a/source4/build/pidl/pidl.pl
+++ b/source4/build/pidl/pidl.pl
@@ -204,7 +204,10 @@ sub process_file($)
$pidl = ODL::ODL2IDL($pidl);
}
- if (defined($opt_header) or defined($opt_eth_parser) or defined($opt_eth_header) or defined($opt_client) or defined($opt_server) or defined($opt_parser) or defined($opt_ejs)) {
+ if (defined($opt_header) or defined($opt_eth_parser) or
+ defined($opt_eth_header) or defined($opt_client) or
+ defined($opt_server) or defined($opt_parser) or
+ defined($opt_ejs)) {
$ndr = Ndr::Parse($pidl);
# print util::MyDumper($ndr);
}