📄 ejs.pm
字号:
#################################################### EJS function wrapper generator# Copyright jelmer@samba.org 2005# Copyright Andrew Tridgell 2005# released under the GNU GPLpackage Parse::Pidl::Samba4::EJS;use Exporter;@ISA = qw(Exporter);@EXPORT_OK = qw(get_pointer_to get_value_of check_null_pointer fn_declare TypeFunctionName);use strict;use Parse::Pidl::Typelist;use Parse::Pidl::Util qw(has_property ParseExpr);use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel);use Parse::Pidl::Samba4::NDR::Parser qw(GenerateStructEnv GenerateFunctionInEnv GenerateFunctionOutEnv);use vars qw($VERSION);$VERSION = '0.01';sub new($) { my ($class) = @_; my $self = { res => "", res_hdr => "", tabs => "", constants => {}}; bless($self, $class);}sub pidl_hdr ($$){ my $self = shift; $self->{res_hdr} .= shift;}sub pidl($$){ my ($self, $d) = @_; if ($d) { $self->{res} .= $self->{tabs}; $self->{res} .= $d; } $self->{res} .= "\n";}sub indent($){ my ($self) = @_; $self->{tabs} .= "\t";}sub deindent($){ my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 0, -1);}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"; }}###################################################################### check that a variable we get from ParseExpr isn't a null pointersub check_null_pointer($$){ my ($self, $size) = @_; if ($size =~ /^\*/) { my $size2 = substr($size, 1); $self->pidl("if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;"); }}###################################################################### work out is a parse function should be declared static or notsub fn_declare($$$){ my ($self,$fn,$decl) = @_; if (has_property($fn, "public")) { $self->pidl_hdr("$decl;\n"); $self->pidl("_PUBLIC_ $decl"); } else { $self->pidl("static $decl"); }}############################ pull a scalar elementsub EjsPullScalar($$$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; return if (has_property($e, "value")); if (ref($e->{TYPE}) eq "HASH" and not defined($e->{TYPE}->{NAME})) { $self->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")) { $var = get_pointer_to($var); } my $t; if (ref($e->{TYPE}) eq "HASH") { $t = "$e->{TYPE}->{TYPE}_$e->{TYPE}->{NAME}"; } else { $t = $e->{TYPE}; } $self->pidl("EJS_CHECK(ejs_pull_$t(ejs, v, $name, $var));"); }}############################ pull a pointer elementsub EjsPullPointer($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; $self->pidl("if (ejs_pull_null(ejs, v, $name)) {"); $self->indent; if ($l->{POINTER_TYPE} eq "ref") { $self->pidl("return NT_STATUS_INVALID_PARAMETER_MIX;"); } else { $self->pidl("$var = NULL;"); } $self->deindent; $self->pidl("} else {"); $self->indent; $self->pidl("EJS_ALLOC(ejs, $var);"); $var = get_value_of($var); $self->EjsPullElement($e, GetNextLevel($e, $l), $var, $name, $env); $self->deindent; $self->pidl("}");}############################ pull a string elementsub EjsPullString($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; my $pl = GetPrevLevel($e, $l); $var = get_pointer_to($var); if (defined($pl) and $pl->{TYPE} eq "POINTER") { $var = get_pointer_to($var); } $self->pidl("EJS_CHECK(ejs_pull_string(ejs, v, $name, $var));");}############################ pull an array elementsub EjsPullArray($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; my $nl = GetNextLevel($e, $l); my $length = ParseExpr($l->{LENGTH_IS}, $env, $e); my $size = ParseExpr($l->{SIZE_IS}, $env, $e); my $pl = GetPrevLevel($e, $l); if ($pl && $pl->{TYPE} eq "POINTER") { $var = get_pointer_to($var); } # uint8 arrays are treated as data blobs if ($nl->{TYPE} eq 'DATA' && $e->{TYPE} eq 'uint8') { if (!$l->{IS_FIXED}) { $self->check_null_pointer($size); $self->pidl("EJS_ALLOC_N(ejs, $var, $size);"); } $self->check_null_pointer($length); $self->pidl("ejs_pull_array_uint8(ejs, v, $name, $var, $length);"); return; } my $avar = $var . "[i]"; $self->pidl("{"); $self->indent; $self->pidl("uint32_t i;"); if (!$l->{IS_FIXED}) { $self->pidl("EJS_ALLOC_N(ejs, $var, $size);"); } $self->pidl("for (i=0;i<$length;i++) {"); $self->indent; $self->pidl("char *id = talloc_asprintf(ejs, \"%s.%u\", $name, i);"); $self->EjsPullElement($e, $nl, $avar, "id", $env); $self->pidl("talloc_free(id);"); $self->deindent; $self->pidl("}"); $self->pidl("ejs_push_uint32(ejs, v, $name \".length\", &i);"); $self->deindent; $self->pidl("}");}############################ pull a switch elementsub EjsPullSwitch($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; my $switch_var = ParseExpr($l->{SWITCH_IS}, $env, $e); $self->pidl("ejs_set_switch(ejs, $switch_var);"); $self->EjsPullElement($e, GetNextLevel($e, $l), $var, $name, $env);}############################ pull a structure elementsub EjsPullElement($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; if (($l->{TYPE} eq "POINTER")) { $self->EjsPullPointer($e, $l, $var, $name, $env); } elsif (has_property($e, "charset")) { $self->EjsPullString($e, $l, $var, $name, $env); } elsif ($l->{TYPE} eq "ARRAY") { $self->EjsPullArray($e, $l, $var, $name, $env); } elsif ($l->{TYPE} eq "DATA") { $self->EjsPullScalar($e, $l, $var, $name, $env); } elsif (($l->{TYPE} eq "SWITCH")) { $self->EjsPullSwitch($e, $l, $var, $name, $env); } else { $self->pidl("return ejs_panic(ejs, \"unhandled pull type $l->{TYPE}\");"); }}############################################## pull a structure/union element at top levelsub EjsPullElementTop($$$){ my ($self, $e, $env) = @_; my $l = $e->{LEVELS}[0]; my $var = ParseExpr($e->{NAME}, $env, $e); my $name = "\"$e->{NAME}\""; $self->EjsPullElement($e, $l, $var, $name, $env);}############################ pull a structsub EjsStructPull($$$){ my ($self, $d, $varname) = @_; my $env = GenerateStructEnv($d, $varname); $self->pidl("EJS_CHECK(ejs_pull_struct_start(ejs, &v, name));"); foreach my $e (@{$d->{ELEMENTS}}) { $self->EjsPullElementTop($e, $env); }}############################ pull a unionsub EjsUnionPull($$$){ my ($self, $d, $varname) = @_; my $have_default = 0; $self->pidl("EJS_CHECK(ejs_pull_struct_start(ejs, &v, name));"); $self->pidl("switch (ejs->switch_var) {"); $self->indent; foreach my $e (@{$d->{ELEMENTS}}) { if ($e->{CASE} eq "default") { $have_default = 1; } $self->pidl("$e->{CASE}:"); $self->indent; if ($e->{TYPE} ne "EMPTY") { $self->EjsPullElementTop($e, { $e->{NAME} => "$varname->$e->{NAME}"}); } $self->pidl("break;"); $self->deindent; } if (! $have_default) { $self->pidl("default:"); $self->indent; $self->pidl("return ejs_panic(ejs, \"Bad switch value\");"); $self->deindent; } $self->deindent; $self->pidl("}");}############################################### put the enum elements in the constants arraysub EjsEnumConstant($$){ my ($self, $d) = @_; my $v = 0; foreach my $e (@{$d->{ELEMENTS}}) { my $el = $e; chomp $el; if ($el =~ /^(.*)=\s*(.*)\s*$/) { $el = $1; $v = $2; } $self->{constants}->{$el} = $v; $v++; }}############################ pull a enumsub EjsEnumPull($$$){ my ($self, $d, $varname) = @_; $self->EjsEnumConstant($d); $self->pidl("unsigned e;"); $self->pidl("EJS_CHECK(ejs_pull_enum(ejs, v, name, &e));"); $self->pidl("*$varname = e;");}############################ pull a bitmapsub EjsBitmapPull($$$){ my ($self, $d, $varname) = @_; my $type_fn = $d->{BASE_TYPE}; $self->pidl("EJS_CHECK(ejs_pull_$type_fn(ejs, v, name, $varname));");}sub EjsTypePullFunction($$$){ sub EjsTypePullFunction($$$); my ($self, $d, $name) = @_; return if (has_property($d, "noejs")); if ($d->{TYPE} eq "TYPEDEF") { $self->EjsTypePullFunction($d->{DATA}, $name); return; } if ($d->{TYPE} eq "STRUCT") { $self->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") { $self->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") { $self->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}); $self->fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, $type_decl *r)"); } $self->pidl("{"); $self->indent; $self->EjsTypePull($d, "r"); $self->pidl("return NT_STATUS_OK;"); $self->deindent; $self->pidl("}\n");}sub EjsTypePull($$$){ my ($self, $d, $varname) = @_; if ($d->{TYPE} eq 'STRUCT') { $self->EjsStructPull($d, $varname); } elsif ($d->{TYPE} eq 'UNION') { $self->EjsUnionPull($d, $varname); } elsif ($d->{TYPE} eq 'ENUM') { $self->EjsEnumPull($d, $varname); } elsif ($d->{TYPE} eq 'BITMAP') { $self->EjsBitmapPull($d, $varname); } else { warn "Unhandled pull $varname of type $d->{TYPE}"; }}###################### generate a functionsub EjsPullFunction($$){ my ($self, $d) = @_; my $env = GenerateFunctionInEnv($d); my $name = $d->{NAME}; $self->pidl("\nstatic NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, struct $name *r)"); $self->pidl("{"); $self->indent; $self->pidl("EJS_CHECK(ejs_pull_struct_start(ejs, &v, \"input\"));"); # we pull non-array elements before array elements as arrays # may have length_is() or size_is() properties that depend # on the non-array elements foreach my $e (@{$d->{ELEMENTS}}) { next unless (grep(/in/, @{$e->{DIRECTION}})); next if (has_property($e, "length_is") || has_property($e, "size_is")); $self->EjsPullElementTop($e, $env); } foreach my $e (@{$d->{ELEMENTS}}) { next unless (grep(/in/, @{$e->{DIRECTION}})); next unless (has_property($e, "length_is") || has_property($e, "size_is")); $self->EjsPullElementTop($e, $env); } $self->pidl("return NT_STATUS_OK;"); $self->deindent; $self->pidl("}\n");}############################ push a scalar elementsub EjsPushScalar($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; if (ref($e->{TYPE}) eq "HASH" and not defined($e->{TYPE}->{NAME})) { $self->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); } $self->pidl("EJS_CHECK(".TypeFunctionName("ejs_push", $e->{TYPE})."(ejs, v, $name, $var));"); }}############################ push a string elementsub EjsPushString($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; my $pl = GetPrevLevel($e, $l); if (defined($pl) and $pl->{TYPE} eq "POINTER") { $var = get_pointer_to($var); } $self->pidl("EJS_CHECK(ejs_push_string(ejs, v, $name, $var));");}############################ push a pointer element
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -