From 79a1b1a928f0f8cdd6c60d74291bf048c8484f0b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 21 Feb 2007 14:35:25 +0000 Subject: r21492: Finish work on nested type support in EJS. (This used to be commit e88055b76a3d81fcc40773d880f76a1c3f53fbf0) --- source4/pidl/TODO | 2 - source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm | 243 ++++++++++++++------------- source4/pidl/lib/Parse/Pidl/Samba4/Header.pm | 4 +- 3 files changed, 127 insertions(+), 122 deletions(-) (limited to 'source4/pidl') diff --git a/source4/pidl/TODO b/source4/pidl/TODO index 2d4ca8a265..47cd956c4f 100644 --- a/source4/pidl/TODO +++ b/source4/pidl/TODO @@ -7,8 +7,6 @@ - strip out pidl-specific properties - support nested elements - - allow non-typedef structs - - generate names for anonymous tagged types. Simple MD5Sum of contents? - support typedefs properly - improve represent_as(): allow it to be used for arrays and other complex types diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm b/source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm index 910b47a4a1..9edd2a4a33 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba4/EJS.pm @@ -110,22 +110,25 @@ sub EjsPullScalar($$$$$) return if (has_property($e, "value")); - my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l); + if (ref($e->{TYPE}) eq "HASH" and not defined($e->{TYPE}->{NAME})) { + EjsTypePull($e->{TYPE}, $var); + } else { + my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l); $var = get_pointer_to($var); # have to handle strings specially :( - if (Parse::Pidl::Typelist::scalar_is_reference($e->{TYPE}) - and (defined($pl) and $pl->{TYPE} eq "POINTER")) { + if (Parse::Pidl::Typelist::scalar_is_reference($e->{TYPE}) + and (defined($pl) and $pl->{TYPE} eq "POINTER")) { $var = get_pointer_to($var); } - my $t; - if (ref($e->{TYPE}) eq "HASH") { - $t = "$e->{TYPE}->{TYPE}_$e->{TYPE}->{NAME}"; - } else { - $t = $e->{TYPE}; + my $t; + if (ref($e->{TYPE}) eq "HASH") { + $t = "$e->{TYPE}->{TYPE}_$e->{TYPE}->{NAME}"; + } else { + $t = $e->{TYPE}; + } + pidl "NDR_CHECK(ejs_pull_$t(ejs, v, $name, $var));"; } - - pidl "NDR_CHECK(ejs_pull_$t(ejs, v, $name, $var));"; } ########################### @@ -163,7 +166,6 @@ sub EjsPullString($$$$$) pidl "NDR_CHECK(ejs_pull_string(ejs, v, $name, $var));"; } - ########################### # pull an array element sub EjsPullArray($$$$$) @@ -250,29 +252,20 @@ sub EjsPullElementTop($$) # pull a struct sub EjsStructPull($$) { - my ($name, $d) = @_; - my $env = GenerateStructEnv($d, "r"); - fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, struct $name *r)"); - pidl "{"; - indent; + my ($d, $varname) = @_; + my $env = GenerateStructEnv($d, $varname); pidl "NDR_CHECK(ejs_pull_struct_start(ejs, &v, name));"; - foreach my $e (@{$d->{ELEMENTS}}) { + foreach my $e (@{$d->{ELEMENTS}}) { EjsPullElementTop($e, $env); } - pidl "return NT_STATUS_OK;"; - deindent; - pidl "}\n"; } ########################### # pull a union sub EjsUnionPull($$) { - my ($name, $d) = @_; + my ($d, $varname) = @_; my $have_default = 0; - fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, union $name *r)"); - pidl "{"; - indent; pidl "NDR_CHECK(ejs_pull_struct_start(ejs, &v, name));"; pidl "switch (ejs->switch_var) {"; indent; @@ -283,7 +276,7 @@ sub EjsUnionPull($$) pidl "$e->{CASE}:"; indent; if ($e->{TYPE} ne "EMPTY") { - EjsPullElementTop($e, { $e->{NAME} => "r->$e->{NAME}"}); + EjsPullElementTop($e, { $e->{NAME} => "$varname->$e->{NAME}"}); } pidl "break;"; deindent; @@ -296,9 +289,6 @@ sub EjsUnionPull($$) } deindent; pidl "}"; - pidl "return NT_STATUS_OK;"; - deindent; - pidl "}"; } ############################################## @@ -323,50 +313,66 @@ sub EjsEnumConstant($) # pull a enum sub EjsEnumPull($$) { - my ($name, $d) = @_; + my ($d, $varname) = @_; EjsEnumConstant($d); - fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, enum $name *r)"); - pidl "{"; - 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"; + pidl "*$varname = e;"; } ########################### # pull a bitmap sub EjsBitmapPull($$) { - my ($name, $d) = @_; + my ($d, $varname) = @_; my $type_fn = $d->{BASE_TYPE}; - my($type_decl) = Parse::Pidl::Typelist::mapTypeName($d->{BASE_TYPE}); - fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, $type_decl *r)"); + pidl "NDR_CHECK(ejs_pull_$type_fn(ejs, v, name, $varname));"; +} + +sub EjsTypePullFunction($$) +{ + sub EjsTypePullFunction($$); + my ($d, $name) = @_; + return if (has_property($d, "noejs")); + + if ($d->{TYPE} eq "TYPEDEF") { + EjsTypePullFunction($d->{DATA}, $name); + return; + } + + if ($d->{TYPE} eq "STRUCT") { + fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, struct $name *r)"); + } elsif ($d->{TYPE} eq "UNION") { + fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, union $name *r)"); + } elsif ($d->{TYPE} eq "ENUM") { + fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, enum $name *r)"); + } elsif ($d->{TYPE} eq "BITMAP") { + my($type_decl) = Parse::Pidl::Typelist::mapTypeName($d->{BASE_TYPE}); + fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, $type_decl *r)"); + } pidl "{"; indent; - pidl "return ejs_pull_$type_fn(ejs, v, name, r);"; + + EjsTypePull($d, "r"); + + pidl "return NT_STATUS_OK;"; deindent; - pidl "}"; + pidl "}\n"; } -########################### -# generate a structure pull -sub EjsTypedefPull($) +sub EjsTypePull($$) { - my $d = shift; - return if (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}); + my ($d, $varname) = @_; + if ($d->{TYPE} eq 'STRUCT') { + EjsStructPull($d, $varname); + } elsif ($d->{TYPE} eq 'UNION') { + EjsUnionPull($d, $varname); + } elsif ($d->{TYPE} eq 'ENUM') { + EjsEnumPull($d, $varname); + } elsif ($d->{TYPE} eq 'BITMAP') { + EjsBitmapPull($d, $varname); } else { - warn "Unhandled pull typedef $d->{NAME} of type $d->{DATA}->{TYPE}"; + warn "Unhandled pull $varname of type $d->{TYPE}"; } } @@ -403,28 +409,32 @@ sub EjsPullFunction($) pidl "}\n"; } - ########################### # push a scalar element sub EjsPushScalar($$$$$) { my ($e, $l, $var, $name, $env) = @_; - # have to handle strings specially :( + + if (ref($e->{TYPE}) eq "HASH" and not defined($e->{TYPE}->{NAME})) { + EjsTypePush($e->{TYPE}, get_pointer_to($var)); + } else { + # have to handle strings specially :( my $pl = GetPrevLevel($e, $l); - if ((not Parse::Pidl::Typelist::scalar_is_reference($e->{TYPE})) - or (defined($pl) and $pl->{TYPE} eq "POINTER")) { - $var = get_pointer_to($var); - } + if ((not Parse::Pidl::Typelist::scalar_is_reference($e->{TYPE})) + or (defined($pl) and $pl->{TYPE} eq "POINTER")) { + $var = get_pointer_to($var); + } - my $t; - if (ref($e->{TYPE}) eq "HASH") { - $t = "$e->{TYPE}->{TYPE}_$e->{TYPE}->{NAME}"; - } else { - $t = $e->{TYPE}; - } + my $t; + if (ref($e->{TYPE}) eq "HASH") { + $t = "$e->{TYPE}->{TYPE}_$e->{TYPE}->{NAME}"; + } else { + $t = $e->{TYPE}; + } - pidl "NDR_CHECK(ejs_push_$t(ejs, v, $name, $var));"; + pidl "NDR_CHECK(ejs_push_$t(ejs, v, $name, $var));"; + } } ########################### @@ -470,7 +480,6 @@ sub EjsPushSwitch($$$$$) EjsPushElement($e, GetNextLevel($e, $l), $var, $name, $env); } - ########################### # push an array element sub EjsPushArray($$$$$) @@ -538,29 +547,20 @@ sub EjsPushElementTop($$) # push a struct sub EjsStructPush($$) { - my ($name, $d) = @_; - my $env = GenerateStructEnv($d, "r"); - fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const struct $name *r)"); - pidl "{"; - indent; + my ($d, $varname) = @_; + my $env = GenerateStructEnv($d, $varname); 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, $d) = @_; + my ($d, $varname) = @_; my $have_default = 0; - fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const union $name *r)"); - pidl "{"; - indent; pidl "NDR_CHECK(ejs_push_struct_start(ejs, &v, name));"; pidl "switch (ejs->switch_var) {"; indent; @@ -571,7 +571,7 @@ sub EjsUnionPush($$) pidl "$e->{CASE}:"; indent; if ($e->{TYPE} ne "EMPTY") { - EjsPushElementTop($e, { $e->{NAME} => "r->$e->{NAME}"} ); + EjsPushElementTop($e, { $e->{NAME} => "$varname->$e->{NAME}"} ); } pidl "break;"; deindent; @@ -584,35 +584,24 @@ sub EjsUnionPush($$) } deindent; pidl "}"; - pidl "return NT_STATUS_OK;"; - deindent; - pidl "}"; } ########################### # push a enum sub EjsEnumPush($$) { - my $name = shift; - my $d = shift; + my ($d, $varname) = @_; EjsEnumConstant($d); - fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const enum $name *r)"); - pidl "{"; - indent; - pidl "unsigned e = *r;"; + pidl "unsigned e = ".get_value_of($varname).";"; 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, $d) = @_; + my ($d, $varname) = @_; my $type_fn = $d->{BASE_TYPE}; - my($type_decl) = Parse::Pidl::Typelist::mapTypeName($d->{BASE_TYPE}); # put the bitmap elements in the constants array foreach my $e (@{$d->{ELEMENTS}}) { if ($e =~ /^(\w*)\s*(.*)\s*$/) { @@ -621,36 +610,55 @@ sub EjsBitmapPush($$) $constants{$bname} = $v; } } - fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const $type_decl *r)"); + pidl "NDR_CHECK(ejs_push_$type_fn(ejs, v, name, $varname));"; +} + +sub EjsTypePushFunction($$) +{ + sub EjsTypePushFunction($$); + my ($d, $name) = @_; + return if (has_property($d, "noejs")); + + if ($d->{TYPE} eq "TYPEDEF") { + EjsTypePushFunction($d->{DATA}, $name); + return; + } + + if ($d->{TYPE} eq "STRUCT") { + fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const struct $name *r)"); + } elsif ($d->{TYPE} eq "UNION") { + fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const union $name *r)"); + } elsif ($d->{TYPE} eq "ENUM") { + fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const enum $name *r)"); + } elsif ($d->{TYPE} eq "BITMAP") { + my($type_decl) = Parse::Pidl::Typelist::mapTypeName($d->{BASE_TYPE}); + fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const $type_decl *r)"); + } pidl "{"; indent; - pidl "return ejs_push_$type_fn(ejs, v, name, r);"; + EjsTypePush($d, "r"); + pidl "return NT_STATUS_OK;"; deindent; - pidl "}"; + pidl "}\n"; } - -########################### -# generate a structure push -sub EjsTypedefPush($) +sub EjsTypePush($$) { - my $d = shift; - return if (has_property($d, "noejs")); + my ($d, $varname) = @_; - 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}); + if ($d->{TYPE} eq 'STRUCT') { + EjsStructPush($d, $varname); + } elsif ($d->{TYPE} eq 'UNION') { + EjsUnionPush($d, $varname); + } elsif ($d->{TYPE} eq 'ENUM') { + EjsEnumPush($d, $varname); + } elsif ($d->{TYPE} eq 'BITMAP') { + EjsBitmapPush($d, $varname); } else { - warn "Unhandled push typedef $d->{NAME} of type $d->{DATA}->{TYPE}"; + warn "Unhandled push $varname of type $d->{TYPE}"; } } - ##################### # generate a function sub EjsPushFunction($) @@ -678,7 +686,6 @@ sub EjsPushFunction($) pidl "}\n"; } - ################################# # generate a ejs mapping function sub EjsFunction($$) @@ -730,8 +737,8 @@ sub EjsInterface($$) pidl_hdr "\n"; foreach my $d (@{$interface->{TYPES}}) { - ($needed->{"push_$d->{NAME}"}) && EjsTypedefPush($d); - ($needed->{"pull_$d->{NAME}"}) && EjsTypedefPull($d); + ($needed->{"push_$d->{NAME}"}) && EjsTypePushFunction($d, $d->{NAME}); + ($needed->{"pull_$d->{NAME}"}) && EjsTypePullFunction($d, $d->{NAME}); } foreach my $d (@{$interface->{FUNCTIONS}}) { diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/Header.pm b/source4/pidl/lib/Parse/Pidl/Samba4/Header.pm index 39e6c4233c..11ecc17001 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba4/Header.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba4/Header.pm @@ -7,7 +7,7 @@ package Parse::Pidl::Samba4::Header; use strict; -use Parse::Pidl::Typelist qw(mapTypeName); +use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference); use Parse::Pidl::Util qw(has_property is_constant); use Parse::Pidl::Samba4 qw(is_intree); @@ -61,7 +61,7 @@ sub HeaderElement($) pidl " "; my $numstar = $element->{POINTERS}; if ($numstar >= 1) { - $numstar-- if Parse::Pidl::Typelist::scalar_is_reference($element->{TYPE}); + $numstar-- if (scalar_is_reference($element->{TYPE})); } foreach (@{$element->{ARRAY_LEN}}) { -- cgit