From 93aba2c0871a0991dceba2a580d4b04f196adec3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 7 Jul 2005 06:23:36 +0000 Subject: 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) --- source4/build/pidl/ejs.pm | 355 ++++++++++++++++++++++++++++++++++++++++++--- source4/build/pidl/pidl.pl | 5 +- 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); } -- cgit