diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2005-07-09 15:32:08 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:19:27 -0500 |
commit | fa1445f4bc962efb3e639d3a4e345b1db14155b7 (patch) | |
tree | 8799d04bc9ec022569fedd636e899bcc29a57935 /source4/build/pidl/Parse/Pidl/Samba/EJS.pm | |
parent | c222331d6d3785075bb0c961315aae9380101e47 (diff) | |
download | samba-fa1445f4bc962efb3e639d3a4e345b1db14155b7.tar.gz samba-fa1445f4bc962efb3e639d3a4e345b1db14155b7.tar.bz2 samba-fa1445f4bc962efb3e639d3a4e345b1db14155b7.zip |
r8264: - Use standard perl package structure for pidl.
- Only "use" pidl modules in the main executable when necessary
Try 'make install' in build/pidl to install the package (should work stand-alone).
(This used to be commit c620095692122a65ae1c5d85ca20468d4de93c54)
Diffstat (limited to 'source4/build/pidl/Parse/Pidl/Samba/EJS.pm')
-rw-r--r-- | source4/build/pidl/Parse/Pidl/Samba/EJS.pm | 734 |
1 files changed, 734 insertions, 0 deletions
diff --git a/source4/build/pidl/Parse/Pidl/Samba/EJS.pm b/source4/build/pidl/Parse/Pidl/Samba/EJS.pm new file mode 100644 index 0000000000..72f280add0 --- /dev/null +++ b/source4/build/pidl/Parse/Pidl/Samba/EJS.pm @@ -0,0 +1,734 @@ +################################################### +# EJS function wrapper generator +# Copyright jelmer@samba.org 2005 +# Copyright Andrew Tridgell 2005 +# released under the GNU GPL + +package Parse::Pidl::Samba::EJS; + +use strict; +use Parse::Pidl::Typelist; + +my($res); +my %constants; + +my $tabs = ""; +sub pidl($) +{ + my $d = shift; + if ($d) { + $res .= $tabs; + $res .= $d; + } + $res .= "\n"; +} + +sub indent() +{ + $tabs .= "\t"; +} + +sub deindent() +{ + $tabs = substr($tabs, 0, -1); +} + +# this should probably be in ndr.pm +sub GenerateStructEnv($) +{ + my $x = shift; + my %env; + + foreach my $e (@{$x->{ELEMENTS}}) { + if ($e->{NAME}) { + $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"; + } +} + +##################################################################### +# work out is a parse function should be declared static or not +sub fn_prefix($) +{ + my $fn = shift; + + return "" if (Parse::Pidl::Util::has_property($fn, "public")); + return "static "; +} + +########################### +# pull a scalar element +sub EjsPullScalar($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + + return if (Parse::Pidl::Util::has_property($e, "value")); + + $var = get_pointer_to($var); + # have to handle strings specially :( + if ($e->{TYPE} eq "string") { + $var = get_pointer_to($var); + } + pidl "NDR_CHECK(ejs_pull_$e->{TYPE}(ejs, v, $name, $var));"; +} + +########################### +# pull a pointer element +sub EjsPullPointer($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + pidl "if (ejs_pull_null(ejs, v, $name)) {"; + indent; + pidl "$var = NULL;"; + deindent; + pidl "} else {"; + indent; + pidl "EJS_ALLOC(ejs, $var);"; + $var = get_value_of($var); + EjsPullElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env); + deindent; + pidl "}"; +} + +########################### +# pull a string element +sub EjsPullString($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + $var = get_pointer_to($var); + pidl "NDR_CHECK(ejs_pull_string(ejs, v, $name, $var));"; +} + + +########################### +# pull an array element +sub EjsPullArray($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env); + my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l); + if ($pl && $pl->{TYPE} eq "POINTER") { + $var = get_pointer_to($var); + } + my $avar = $var . "[i]"; + pidl "{"; + indent; + pidl "uint32_t i;"; + if (!$l->{IS_FIXED}) { + pidl "EJS_ALLOC_N(ejs, $var, $length);"; + } + pidl "for (i=0;i<$length;i++) {"; + indent; + pidl "char *id = talloc_asprintf(ejs, \"%s.%u\", $name, i);"; + EjsPullElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $avar, "id", $env); + pidl "talloc_free(id);"; + deindent; + pidl "}"; + pidl "ejs_push_uint32(ejs, v, $name \".length\", &i);"; + deindent; + pidl "}"; +} + +########################### +# pull a switch element +sub EjsPullSwitch($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env); + pidl "ejs_set_switch(ejs, $switch_var);"; + EjsPullElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env); +} + +########################### +# pull a structure element +sub EjsPullElement($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + if (Parse::Pidl::Util::has_property($e, "charset")) { + EjsPullString($e, $l, $var, $name, $env); + } elsif ($l->{TYPE} eq "ARRAY") { + EjsPullArray($e, $l, $var, $name, $env); + } elsif ($l->{TYPE} eq "DATA") { + EjsPullScalar($e, $l, $var, $name, $env); + } elsif (($l->{TYPE} eq "POINTER")) { + EjsPullPointer($e, $l, $var, $name, $env); + } elsif (($l->{TYPE} eq "SWITCH")) { + EjsPullSwitch($e, $l, $var, $name, $env); + } else { + pidl "return ejs_panic(ejs, \"unhandled pull type $l->{TYPE}\");"; + } +} + +############################################# +# pull a structure/union element at top level +sub EjsPullElementTop($$) +{ + my $e = shift; + my $env = shift; + my $l = $e->{LEVELS}[0]; + my $var = Parse::Pidl::Util::ParseExpr($e->{NAME}, $env); + my $name = "\"$e->{NAME}\""; + EjsPullElement($e, $l, $var, $name, $env); +} + +########################### +# pull a struct +sub EjsStructPull($$) +{ + my $name = shift; + my $d = shift; + my $env = GenerateStructEnv($d); + pidl fn_prefix($d); + pidl "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, struct $name *r)\n{"; + indent; + pidl "NDR_CHECK(ejs_pull_struct_start(ejs, &v, name));"; + foreach my $e (@{$d->{ELEMENTS}}) { + EjsPullElementTop($e, $env); + } + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}\n"; +} + +########################### +# pull a union +sub EjsUnionPull($$) +{ + my $name = shift; + my $d = shift; + my $have_default = 0; + my $env = GenerateStructEnv($d); + pidl fn_prefix($d); + pidl "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, union $name *r)\n{"; + indent; + pidl "NDR_CHECK(ejs_pull_struct_start(ejs, &v, name));"; + pidl "switch (ejs->switch_var) {"; + indent; + foreach my $e (@{$d->{ELEMENTS}}) { + if ($e->{CASE} eq "default") { + $have_default = 1; + } + pidl "$e->{CASE}:"; + indent; + if ($e->{TYPE} ne "EMPTY") { + EjsPullElementTop($e, $env); + } + pidl "break;"; + deindent; + } + if (! $have_default) { + pidl "default:"; + indent; + pidl "return ejs_panic(ejs, \"Bad switch value\");"; + deindent; + } + deindent; + pidl "}"; + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}"; +} + +########################### +# pull a enum +sub EjsEnumPull($$) +{ + my $name = shift; + my $d = shift; + pidl fn_prefix($d); + pidl "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, enum $name *r)\n{"; + indent; + pidl "unsigned e;"; + pidl "NDR_CHECK(ejs_pull_enum(ejs, v, name, &e));"; + pidl "*r = e;"; + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}\n"; +} + +########################### +# pull a bitmap +sub EjsBitmapPull($$) +{ + my $name = shift; + my $d = shift; + my $type_fn = $d->{BASE_TYPE}; + my($type_decl) = Parse::Pidl::Typelist::mapType($d->{BASE_TYPE}); + pidl fn_prefix($d); + pidl "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, $type_decl *r)\n{"; + indent; + pidl "return ejs_pull_$type_fn(ejs, v, name, r);"; + deindent; + pidl "}"; +} + + +########################### +# generate a structure pull +sub EjsTypedefPull($) +{ + my $d = shift; + return if (Parse::Pidl::Util::has_property($d, "noejs")); + if ($d->{DATA}->{TYPE} eq 'STRUCT') { + EjsStructPull($d->{NAME}, $d->{DATA}); + } elsif ($d->{DATA}->{TYPE} eq 'UNION') { + EjsUnionPull($d->{NAME}, $d->{DATA}); + } elsif ($d->{DATA}->{TYPE} eq 'ENUM') { + EjsEnumPull($d->{NAME}, $d->{DATA}); + } elsif ($d->{DATA}->{TYPE} eq 'BITMAP') { + EjsBitmapPull($d->{NAME}, $d->{DATA}); + } else { + warn "Unhandled pull typedef $d->{NAME} of type $d->{DATA}->{TYPE}"; + } +} + +##################### +# generate a function +sub EjsPullFunction($) +{ + my $d = shift; + my $env = GenerateFunctionInEnv($d); + my $name = $d->{NAME}; + + pidl "\nstatic NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, struct $name *r)"; + pidl "{"; + indent; + pidl "NDR_CHECK(ejs_pull_struct_start(ejs, &v, \"input\"));"; + + foreach my $e (@{$d->{ELEMENTS}}) { + next unless (grep(/in/, @{$e->{DIRECTION}})); + EjsPullElementTop($e, $env); + } + + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}\n"; +} + + +########################### +# push a scalar element +sub EjsPushScalar($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + $var = get_pointer_to($var); + pidl "NDR_CHECK(ejs_push_$e->{TYPE}(ejs, v, $name, $var));"; +} + +########################### +# push a string element +sub EjsPushString($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + pidl "NDR_CHECK(ejs_push_string(ejs, v, $name, $var));"; +} + +########################### +# push a pointer element +sub EjsPushPointer($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + pidl "if (NULL == $var) {"; + indent; + pidl "NDR_CHECK(ejs_push_null(ejs, v, $name));"; + deindent; + pidl "} else {"; + indent; + $var = get_value_of($var); + EjsPushElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env); + deindent; + pidl "}"; +} + +########################### +# push a switch element +sub EjsPushSwitch($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env); + pidl "ejs_set_switch(ejs, $switch_var);"; + EjsPushElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env); +} + + +########################### +# push an array element +sub EjsPushArray($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env); + my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l); + if ($pl && $pl->{TYPE} eq "POINTER") { + $var = get_pointer_to($var); + } + my $avar = $var . "[i]"; + pidl "{"; + indent; + pidl "uint32_t i;"; + pidl "for (i=0;i<$length;i++) {"; + indent; + pidl "const char *id = talloc_asprintf(ejs, \"%s.%u\", $name, i);"; + EjsPushElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $avar, "id", $env); + deindent; + pidl "}"; + pidl "ejs_push_uint32(ejs, v, $name \".length\", &i);"; + deindent; + pidl "}"; +} + +################################ +# push a structure/union element +sub EjsPushElement($$$$$) +{ + my ($e, $l, $var, $name, $env) = @_; + if (Parse::Pidl::Util::has_property($e, "charset")) { + EjsPushString($e, $l, $var, $name, $env); + } elsif ($l->{TYPE} eq "ARRAY") { + EjsPushArray($e, $l, $var, $name, $env); + } elsif ($l->{TYPE} eq "DATA") { + EjsPushScalar($e, $l, $var, $name, $env); + } elsif (($l->{TYPE} eq "POINTER")) { + EjsPushPointer($e, $l, $var, $name, $env); + } elsif (($l->{TYPE} eq "SWITCH")) { + EjsPushSwitch($e, $l, $var, $name, $env); + } else { + pidl "return ejs_panic(ejs, \"unhandled push type $l->{TYPE}\");"; + } +} + +############################################# +# push a structure/union element at top level +sub EjsPushElementTop($$) +{ + my $e = shift; + my $env = shift; + my $l = $e->{LEVELS}[0]; + my $var = Parse::Pidl::Util::ParseExpr($e->{NAME}, $env); + my $name = "\"$e->{NAME}\""; + EjsPushElement($e, $l, $var, $name, $env); +} + +########################### +# push a struct +sub EjsStructPush($$) +{ + my $name = shift; + my $d = shift; + my $env = GenerateStructEnv($d); + pidl fn_prefix($d); + pidl "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const struct $name *r)\n{"; + indent; + pidl "NDR_CHECK(ejs_push_struct_start(ejs, &v, name));"; + foreach my $e (@{$d->{ELEMENTS}}) { + EjsPushElementTop($e, $env); + } + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}\n"; +} + +########################### +# push a union +sub EjsUnionPush($$) +{ + my $name = shift; + my $d = shift; + my $have_default = 0; + my $env = GenerateStructEnv($d); + pidl fn_prefix($d); + pidl "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const union $name *r)\n{"; + indent; + pidl "NDR_CHECK(ejs_push_struct_start(ejs, &v, name));"; + pidl "switch (ejs->switch_var) {"; + indent; + foreach my $e (@{$d->{ELEMENTS}}) { + if ($e->{CASE} eq "default") { + $have_default = 1; + } + pidl "$e->{CASE}:"; + indent; + if ($e->{TYPE} ne "EMPTY") { + EjsPushElementTop($e, $env); + } + pidl "break;"; + deindent; + } + if (! $have_default) { + pidl "default:"; + indent; + pidl "return ejs_panic(ejs, \"Bad switch value\");"; + deindent; + } + deindent; + pidl "}"; + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}"; +} + +########################### +# push a enum +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++; + } + 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; + pidl "unsigned e = *r;"; + pidl "NDR_CHECK(ejs_push_enum(ejs, v, name, &e));"; + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}\n"; +} + +########################### +# push a bitmap +sub EjsBitmapPush($$) +{ + my $name = shift; + my $d = shift; + my $type_fn = $d->{BASE_TYPE}; + my($type_decl) = Parse::Pidl::Typelist::mapType($d->{BASE_TYPE}); + # put the bitmap elements in the constants array + foreach my $e (@{$d->{ELEMENTS}}) { + if ($e =~ /^(\w*)\s*(.*)\s*$/) { + my $bname = $1; + my $v = $2; + $constants{$bname} = $v; + } + } + pidl fn_prefix($d); + pidl "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const $type_decl *r)\n{"; + indent; + pidl "return ejs_push_$type_fn(ejs, v, name, r);"; + deindent; + pidl "}"; +} + + +########################### +# generate a structure push +sub EjsTypedefPush($) +{ + my $d = shift; + return if (Parse::Pidl::Util::has_property($d, "noejs")); + if ($d->{DATA}->{TYPE} eq 'STRUCT') { + EjsStructPush($d->{NAME}, $d->{DATA}); + } elsif ($d->{DATA}->{TYPE} eq 'UNION') { + EjsUnionPush($d->{NAME}, $d->{DATA}); + } elsif ($d->{DATA}->{TYPE} eq 'ENUM') { + EjsEnumPush($d->{NAME}, $d->{DATA}); + } elsif ($d->{DATA}->{TYPE} eq 'BITMAP') { + EjsBitmapPush($d->{NAME}, $d->{DATA}); + } else { + warn "Unhandled push typedef $d->{NAME} of type $d->{DATA}->{TYPE}"; + } +} + + +##################### +# 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)"; + pidl "{"; + indent; + pidl "NDR_CHECK(ejs_push_struct_start(ejs, &v, \"output\"));"; + + foreach my $e (@{$d->{ELEMENTS}}) { + next unless (grep(/out/, @{$e->{DIRECTION}})); + EjsPushElementTop($e, $env); + } + + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}\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)"; + 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);"; + deindent; + pidl "}\n"; +} + +################### +# handle a constant +sub EjsConst($) +{ + my $const = shift; + $constants{$const->{NAME}} = $const->{VALUE}; +} + +##################################################################### +# parse the interface definitions +sub EjsInterface($) +{ + my($interface) = shift; + my @fns = (); + my $name = $interface->{NAME}; + + %constants = (); + + foreach my $d (@{$interface->{TYPEDEFS}}) { + EjsTypedefPush($d); + EjsTypedefPull($d); + } + + foreach my $d (@{$interface->{FUNCTIONS}}) { + next if not defined($d->{OPNUM}); + + EjsPullFunction($d); + EjsPushFunction($d); + EjsFunction($d); + + push (@fns, $d->{NAME}); + } + + foreach my $d (@{$interface->{CONSTS}}) { + EjsConst($d); + } + + pidl "void setup_ejs_$name(void)"; + pidl "{"; + indent; + foreach (@fns) { + pidl "ejsDefineCFunction(-1, \"dcerpc_$_\", ejs_$_, NULL, MPR_VAR_SCRIPT_HANDLE);"; + } + 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);"; + } else { + pidl "ejs_set_constant_int(eid, \"$v\", $value);"; + } + } + deindent; + pidl "}\n"; + + pidl "NTSTATUS ejs_init_$name(void)"; + pidl "{"; + indent; + pidl "return smbcalls_register_ejs(\"$name\", setup_ejs_$name, setup_ejs_constants_$name);"; + deindent; + pidl "}"; +} + +##################################################################### +# parse a parsed IDL into a C header +sub Parse($$) +{ + my($ndr,$hdr) = @_; + + my $ejs_hdr = $hdr; + $ejs_hdr =~ s/.h$/_ejs.h/; + $res = ""; + pidl " +/* EJS wrapper functions auto-generated by pidl */ +#include \"includes.h\" +#include \"lib/ejs/ejs.h\" +#include \"scripting/ejs/ejsrpc.h\" +#include \"librpc/gen_ndr/ndr_misc_ejs.h\" +#include \"$hdr\" +#include \"$ejs_hdr\" + +"; + foreach my $x (@{$ndr}) { + if ($x->{TYPE} eq "INTERFACE") { + ($x->{TYPE} eq "INTERFACE") && EjsInterface($x); + } + } + + return $res; +} + +1; |