📄 ejs.pm
字号:
sub EjsPushPointer($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; $self->pidl("if (NULL == $var) {"); $self->indent; if ($l->{POINTER_TYPE} eq "ref") { $self->pidl("return NT_STATUS_INVALID_PARAMETER_MIX;"); } else { $self->pidl("EJS_CHECK(ejs_push_null(ejs, v, $name));"); } $self->deindent; $self->pidl("} else {"); $self->indent; $var = get_value_of($var); $self->EjsPushElement($e, GetNextLevel($e, $l), $var, $name, $env); $self->deindent; $self->pidl("}");}############################ push a switch elementsub EjsPushSwitch($$$$$$){ 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->EjsPushElement($e, GetNextLevel($e, $l), $var, $name, $env);}############################ push an array elementsub EjsPushArray($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; my $nl = GetNextLevel($e, $l); my $length = ParseExpr($l->{LENGTH_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') { $self->check_null_pointer($length); $self->pidl("ejs_push_array_uint8(ejs, v, $name, $var, $length);"); return; } my $avar = $var . "[i]"; $self->pidl("{"); $self->indent; $self->pidl("uint32_t i;"); $self->pidl("for (i=0;i<$length;i++) {"); $self->indent; $self->pidl("const char *id = talloc_asprintf(ejs, \"%s.%u\", $name, i);"); $self->EjsPushElement($e, $nl, $avar, "id", $env); $self->deindent; $self->pidl("}"); $self->pidl("ejs_push_uint32(ejs, v, $name \".length\", &i);"); $self->deindent; $self->pidl("}");}################################# push a structure/union elementsub EjsPushElement($$$$$$){ my ($self, $e, $l, $var, $name, $env) = @_; if (($l->{TYPE} eq "POINTER")) { $self->EjsPushPointer($e, $l, $var, $name, $env); } elsif (has_property($e, "charset")) { $self->EjsPushString($e, $l, $var, $name, $env); } elsif ($l->{TYPE} eq "ARRAY") { $self->EjsPushArray($e, $l, $var, $name, $env); } elsif ($l->{TYPE} eq "DATA") { $self->EjsPushScalar($e, $l, $var, $name, $env); } elsif (($l->{TYPE} eq "SWITCH")) { $self->EjsPushSwitch($e, $l, $var, $name, $env); } else { $self->pidl("return ejs_panic(ejs, \"unhandled push type $l->{TYPE}\");"); }}############################################## push a structure/union element at top levelsub EjsPushElementTop($$$){ my ($self, $e, $env) = @_; my $l = $e->{LEVELS}[0]; my $var = ParseExpr($e->{NAME}, $env, $e); my $name = "\"$e->{NAME}\""; $self->EjsPushElement($e, $l, $var, $name, $env);}############################ push a structsub EjsStructPush($$$){ my ($self, $d, $varname) = @_; my $env = GenerateStructEnv($d, $varname); $self->pidl("EJS_CHECK(ejs_push_struct_start(ejs, &v, name));"); foreach my $e (@{$d->{ELEMENTS}}) { $self->EjsPushElementTop($e, $env); }}############################ push a unionsub EjsUnionPush($$$){ my ($self, $d, $varname) = @_; my $have_default = 0; $self->pidl("EJS_CHECK(ejs_push_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->EjsPushElementTop($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("}");}############################ push a enumsub EjsEnumPush($$$){ my ($self, $d, $varname) = @_; $self->EjsEnumConstant($d); $self->pidl("unsigned e = ".get_value_of($varname).";"); $self->pidl("EJS_CHECK(ejs_push_enum(ejs, v, name, &e));");}############################ push a bitmapsub EjsBitmapPush($$$){ my ($self, $d, $varname) = @_; my $type_fn = $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; $self->{constants}->{$bname} = $v; } } $self->pidl("EJS_CHECK(ejs_push_$type_fn(ejs, v, name, $varname));");}sub EjsTypePushFunction($$$){ sub EjsTypePushFunction($$$); my ($self, $d, $name) = @_; return if (has_property($d, "noejs")); my $var = undef; my $dt = $d; if ($dt->{TYPE} eq "TYPEDEF") { $dt = $dt->{DATA}; } if ($dt->{TYPE} eq "STRUCT") { $var = "const struct $name *r"; } elsif ($dt->{TYPE} eq "UNION") { $var = "const union $name *r"; } elsif ($dt->{TYPE} eq "ENUM") { $var = "const enum $name *r"; } elsif ($dt->{TYPE} eq "BITMAP") { my($type_decl) = Parse::Pidl::Typelist::mapTypeName($dt->{BASE_TYPE}); $var = "const $type_decl *r"; } $self->fn_declare($d, "NTSTATUS ".TypeFunctionName("ejs_push", $d) . "(struct ejs_rpc *ejs, struct MprVar *v, const char *name, $var)"); $self->pidl("{"); $self->indent; $self->EjsTypePush($d, "r"); $self->pidl("return NT_STATUS_OK;"); $self->deindent; $self->pidl("}\n");}sub EjsTypePush($$$){ sub EjsTypePush($$$); my ($self, $d, $varname) = @_; if ($d->{TYPE} eq 'STRUCT') { $self->EjsStructPush($d, $varname); } elsif ($d->{TYPE} eq 'UNION') { $self->EjsUnionPush($d, $varname); } elsif ($d->{TYPE} eq 'ENUM') { $self->EjsEnumPush($d, $varname); } elsif ($d->{TYPE} eq 'BITMAP') { $self->EjsBitmapPush($d, $varname); } elsif ($d->{TYPE} eq 'TYPEDEF') { $self->EjsTypePush($d->{DATA}, $varname); } else { warn "Unhandled push $varname of type $d->{TYPE}"; }}###################### generate a functionsub EjsPushFunction($$){ my ($self, $d) = @_; my $env = GenerateFunctionOutEnv($d); $self->pidl("\nstatic NTSTATUS ejs_push_$d->{NAME}(struct ejs_rpc *ejs, struct MprVar *v, const struct $d->{NAME} *r)"); $self->pidl("{"); $self->indent; $self->pidl("EJS_CHECK(ejs_push_struct_start(ejs, &v, \"output\"));"); foreach my $e (@{$d->{ELEMENTS}}) { next unless (grep(/out/, @{$e->{DIRECTION}})); $self->EjsPushElementTop($e, $env); } if ($d->{RETURN_TYPE}) { $self->pidl("EJS_CHECK(".TypeFunctionName("ejs_push", $d->{RETURN_TYPE})."(ejs, v, \"result\", &r->out.result));"); } $self->pidl("return NT_STATUS_OK;"); $self->deindent; $self->pidl("}\n");}################################## generate a ejs mapping functionsub EjsFunction($$$){ my ($self, $d, $iface) = @_; my $name = $d->{NAME}; my $callnum = uc("NDR_$name"); my $table = "&ndr_table_$iface"; $self->pidl("static int ejs_$name(int eid, int argc, struct MprVar **argv)"); $self->pidl("{"); $self->indent; $self->pidl("return ejs_rpc_call(eid, argc, argv, $table, $callnum, (ejs_pull_function_t)ejs_pull_$name, (ejs_push_function_t)ejs_push_$name);"); $self->deindent; $self->pidl("}\n");}#################### handle a constantsub EjsConst($$){ my ($self, $const) = @_; $self->{constants}->{$const->{NAME}} = $const->{VALUE};}sub EjsImport{ my $self = shift; my @imports = @_; foreach (@imports) { s/\.idl\"$//; s/^\"//; $self->pidl_hdr("#include \"librpc/gen_ndr/ndr_$_\_ejs\.h\"\n"); }}###################################################################### parse the interface definitionssub EjsInterface($$$){ my($self,$interface,$needed) = @_; my @fns = (); my $name = $interface->{NAME}; $self->pidl_hdr("#ifndef _HEADER_EJS_$interface->{NAME}\n"); $self->pidl_hdr("#define _HEADER_EJS_$interface->{NAME}\n\n"); $self->pidl_hdr("\n"); foreach my $d (@{$interface->{TYPES}}) { ($needed->{TypeFunctionName("ejs_push", $d)}) && $self->EjsTypePushFunction($d, $d->{NAME}); ($needed->{TypeFunctionName("ejs_pull", $d)}) && $self->EjsTypePullFunction($d, $d->{NAME}); } foreach my $d (@{$interface->{FUNCTIONS}}) { next if not defined($d->{OPNUM}); next if has_property($d, "noejs"); $self->EjsPullFunction($d); $self->EjsPushFunction($d); $self->EjsFunction($d, $name); push (@fns, $d->{NAME}); } foreach my $d (@{$interface->{CONSTS}}) { $self->EjsConst($d); } $self->pidl("static int ejs_$name\_init(int eid, int argc, struct MprVar **argv)"); $self->pidl("{"); $self->indent; $self->pidl("struct MprVar *obj = mprInitObject(eid, \"$name\", argc, argv);"); foreach (@fns) { $self->pidl("mprSetCFunction(obj, \"$_\", ejs_$_);"); } foreach my $v (keys %{$self->{constants}}) { my $value = $self->{constants}->{$v}; if (substr($value, 0, 1) eq "\"") { $self->pidl("mprSetVar(obj, \"$v\", mprString($value));"); } else { $self->pidl("mprSetVar(obj, \"$v\", mprCreateNumberVar($value));"); } } $self->pidl("return ejs_rpc_init(obj, \"$name\");"); $self->deindent; $self->pidl("}\n"); $self->pidl("NTSTATUS ejs_init_$name(void)"); $self->pidl("{"); $self->indent; $self->pidl("ejsDefineCFunction(-1, \"$name\_init\", ejs_$name\_init, NULL, MPR_VAR_SCRIPT_HANDLE);"); $self->pidl("return NT_STATUS_OK;"); $self->deindent; $self->pidl("}"); $self->pidl_hdr("\n"); $self->pidl_hdr("#endif /* _HEADER_EJS_$interface->{NAME} */\n");}###################################################################### parse a parsed IDL into a C headersub Parse($$$){ my($self,$ndr,$hdr) = @_; my $ejs_hdr = $hdr; $ejs_hdr =~ s/.h$/_ejs.h/; $self->pidl_hdr("/* header auto-generated by pidl */\n\n"); $self->pidl("/* EJS wrapper functions auto-generated by pidl */#include \"includes.h\"#include \"librpc/rpc/dcerpc.h\"#include \"lib/appweb/ejs/ejs.h\"#include \"scripting/ejs/ejsrpc.h\"#include \"scripting/ejs/smbcalls.h\"#include \"librpc/gen_ndr/ndr_misc_ejs.h\"#include \"$hdr\"#include \"$ejs_hdr\""); my %needed = (); foreach my $x (@{$ndr}) { ($x->{TYPE} eq "INTERFACE") && NeededInterface($x, \%needed); } foreach my $x (@$ndr) { ($x->{TYPE} eq "INTERFACE") && $self->EjsInterface($x, \%needed); ($x->{TYPE} eq "IMPORT") && $self->EjsImport(@{$x->{PATHS}}); } return ($self->{res_hdr}, $self->{res});}sub NeededFunction($$){ my ($fn,$needed) = @_; $needed->{"ejs_pull_$fn->{NAME}"} = 1; $needed->{"ejs_push_$fn->{NAME}"} = 1; foreach (@{$fn->{ELEMENTS}}) { next if (has_property($_, "subcontext")); #FIXME: Support subcontexts if (grep(/in/, @{$_->{DIRECTION}})) { $needed->{TypeFunctionName("ejs_pull", $_->{TYPE})} = 1; } if (grep(/out/, @{$_->{DIRECTION}})) { $needed->{TypeFunctionName("ejs_push", $_->{TYPE})} = 1; } }}sub NeededType($$$){ sub NeededType($$$); my ($t,$needed,$req) = @_; NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF"); return if (($t->{TYPE} ne "STRUCT") and ($t->{TYPE} ne "UNION")); foreach (@{$t->{ELEMENTS}}) { next if (has_property($_, "subcontext")); #FIXME: Support subcontexts my $n; if (ref($_->{TYPE}) ne "HASH" or defined($_->{TYPE}->{NAME})) { $needed->{TypeFunctionName("ejs_$req", $_->{TYPE})} = 1; } NeededType($_->{TYPE}, $needed, $req) if (ref($_->{TYPE}) eq "HASH"); }}###################################################################### work out what parse functions are neededsub NeededInterface($$){ my ($interface,$needed) = @_; NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}}); foreach (reverse @{$interface->{TYPES}}) { if (has_property($_, "public")) { $needed->{TypeFunctionName("ejs_pull", $_)} = not has_property($_, "noejs"); $needed->{TypeFunctionName("ejs_push", $_)} = not has_property($_, "noejs"); } NeededType($_, $needed, "pull") if ($needed->{TypeFunctionName("ejs_pull", $_)}); NeededType($_, $needed, "push") if ($needed->{TypeFunctionName("ejs_push", $_)}); }}sub TypeFunctionName($$){ my ($prefix, $t) = @_; return "$prefix\_$t->{NAME}" if (ref($t) eq "HASH" and ($t->{TYPE} eq "TYPEDEF" or $t->{TYPE} eq "DECLARE")); return "$prefix\_$t->{TYPE}_$t->{NAME}" if (ref($t) eq "HASH"); return "$prefix\_$t";}1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -