parser.pm
来自「samba最新软件」· PM 代码 · 共 2,327 行 · 第 1/5 页
PM
2,327 行
my ($e,$t,$name,$varname) = @_; return ($t ne "pull"?"const ":"") . "union $name *$varname";}sub ArgsUnionNdrSize($$){ my ($d,$name) = @_; return "const union $name *r, uint32_t level, int flags";}$typefamily{UNION} = { PUSH_FN_BODY => \&ParseUnionPush, DECL => \&DeclUnion, PULL_FN_BODY => \&ParseUnionPull, PRINT_FN_BODY => \&ParseUnionPrint, SIZE_FN_ARGS => \&ArgsUnionNdrSize, SIZE_FN_BODY => \&ParseUnionNdrSize,}; ###################################################################### parse a typedef - push sidesub ParseTypedefPush($$$){ my($self,$e,$varname) = @_; $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($self, $e->{DATA}, $varname);}###################################################################### parse a typedef - pull sidesub ParseTypedefPull($$$){ my($self,$e,$varname) = @_; $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($self, $e->{DATA}, $varname);}###################################################################### parse a typedef - print sidesub ParseTypedefPrint($$$$){ my($self,$e,$name,$varname) = @_; $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($self, $e->{DATA}, $name, $varname);}####################################################################### calculate the size of a structuresub ParseTypedefNdrSize($$$$){ my($self,$t,$name,$varname) = @_; $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN_BODY}->($self, $t->{DATA}, $name, $varname);}sub DeclTypedef($$$$){ my ($e, $t, $name, $varname) = @_; return $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e->{DATA}, $t, $name, $varname);}sub ArgsTypedefNdrSize($$$){ my ($d, $name, $varname) = @_; return $typefamily{$d->{DATA}->{TYPE}}->{SIZE_FN_ARGS}->($d->{DATA}, $name, $varname);}$typefamily{TYPEDEF} = { PUSH_FN_BODY => \&ParseTypedefPush, DECL => \&DeclTypedef, PULL_FN_BODY => \&ParseTypedefPull, PRINT_FN_BODY => \&ParseTypedefPrint, SIZE_FN_ARGS => \&ArgsTypedefNdrSize, SIZE_FN_BODY => \&ParseTypedefNdrSize,};###################################################################### parse a function - print sidesub ParseFunctionPrint($$){ my($self, $fn) = @_; $self->pidl_hdr("void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, const struct $fn->{NAME} *r);"); return if has_property($fn, "noprint"); $self->pidl("_PUBLIC_ void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, const struct $fn->{NAME} *r)"); $self->pidl("{"); $self->indent; foreach my $e (@{$fn->{ELEMENTS}}) { $self->DeclareArrayVariables($e); } $self->pidl("ndr_print_struct(ndr, name, \"$fn->{NAME}\");"); $self->pidl("ndr->depth++;"); $self->pidl("if (flags & NDR_SET_VALUES) {"); $self->pidl("\tndr->flags |= LIBNDR_PRINT_SET_VALUES;"); $self->pidl("}"); $self->pidl("if (flags & NDR_IN) {"); $self->indent; $self->pidl("ndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");"); $self->pidl("ndr->depth++;"); my $env = GenerateFunctionInEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/in/,@{$e->{DIRECTION}})) { $self->ParseElementPrint($e, $env->{$e->{NAME}}, $env); } } $self->pidl("ndr->depth--;"); $self->deindent; $self->pidl("}"); $self->pidl("if (flags & NDR_OUT) {"); $self->indent; $self->pidl("ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");"); $self->pidl("ndr->depth++;"); $env = GenerateFunctionOutEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/out/,@{$e->{DIRECTION}})) { $self->ParseElementPrint($e, $env->{$e->{NAME}}, $env); } } if ($fn->{RETURN_TYPE}) { $self->pidl("ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);"); } $self->pidl("ndr->depth--;"); $self->deindent; $self->pidl("}"); $self->pidl("ndr->depth--;"); $self->deindent; $self->pidl("}"); $self->pidl("");}###################################################################### parse a functionsub ParseFunctionPush($$){ my($self, $fn) = @_; $self->fn_declare("push", $fn, "enum ndr_err_code ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, const struct $fn->{NAME} *r)") or return; return if has_property($fn, "nopush"); $self->pidl("{"); $self->indent; foreach my $e (@{$fn->{ELEMENTS}}) { $self->DeclareArrayVariables($e); } $self->pidl("if (flags & NDR_IN) {"); $self->indent; my $env = GenerateFunctionInEnv($fn); EnvSubstituteValue($env, $fn); foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/in/,@{$e->{DIRECTION}})) { $self->ParseElementPush($e, "ndr", $env, 1, 1); } } $self->deindent; $self->pidl("}"); $self->pidl("if (flags & NDR_OUT) {"); $self->indent; $env = GenerateFunctionOutEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { if (grep(/out/,@{$e->{DIRECTION}})) { $self->ParseElementPush($e, "ndr", $env, 1, 1); } } if ($fn->{RETURN_TYPE}) { $self->pidl("NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));"); } $self->deindent; $self->pidl("}"); $self->pidl("return NDR_ERR_SUCCESS;"); $self->deindent; $self->pidl("}"); $self->pidl("");}sub AllocateArrayLevel($$$$$$){ my ($self,$e,$l,$ndr,$var,$size) = @_; my $pl = GetPrevLevel($e, $l); if (defined($pl) and $pl->{TYPE} eq "POINTER" and $pl->{POINTER_TYPE} eq "ref" and not $l->{IS_ZERO_TERMINATED}) { $self->pidl("if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); $self->pidl("\tNDR_PULL_ALLOC_N($ndr, $var, $size);"); $self->pidl("}"); if (grep(/in/,@{$e->{DIRECTION}}) and grep(/out/,@{$e->{DIRECTION}})) { $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));"); } return; } $self->pidl("NDR_PULL_ALLOC_N($ndr, $var, $size);");}###################################################################### parse a functionsub ParseFunctionPull($$){ my($self,$fn) = @_; # pull function args $self->fn_declare("pull", $fn, "enum ndr_err_code ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)") or return; $self->pidl("{"); $self->indent; # declare any internal pointers we need foreach my $e (@{$fn->{ELEMENTS}}) { $self->DeclarePtrVariables($e); $self->DeclareArrayVariables($e); } my %double_cases = (); foreach my $e (@{$fn->{ELEMENTS}}) { next if ($e->{TYPE} eq "EMPTY"); next if ($double_cases{"$e->{NAME}"}); $self->DeclareMemCtxVariables($e); $double_cases{"$e->{NAME}"} = 1; } $self->pidl("if (flags & NDR_IN) {"); $self->indent; # auto-init the out section of a structure. I originally argued that # this was a bad idea as it hides bugs, but coping correctly # with initialisation and not wiping ref vars is turning # out to be too tricky (tridge) foreach my $e (@{$fn->{ELEMENTS}}) { next unless grep(/out/, @{$e->{DIRECTION}}); $self->pidl("ZERO_STRUCT(r->out);"); $self->pidl(""); last; } my $env = GenerateFunctionInEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { next unless (grep(/in/, @{$e->{DIRECTION}})); $self->ParseElementPull($e, "ndr", $env, 1, 1); } # allocate the "simple" out ref variables. FIXME: Shouldn't this have it's # own flag rather than be in NDR_IN ? foreach my $e (@{$fn->{ELEMENTS}}) { next unless (grep(/out/, @{$e->{DIRECTION}})); next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref"); next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and ($e->{LEVELS}[1]->{DATA_TYPE} eq "string")); next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY") and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED}); if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") { my $size = ParseExprExt($e->{LEVELS}[1]->{SIZE_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return ndr_pull_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), check_fully_dereferenced($e, $env)); $self->pidl("NDR_PULL_ALLOC_N(ndr, r->out.$e->{NAME}, $size);"); if (grep(/in/, @{$e->{DIRECTION}})) { $self->pidl("memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, ($size) * sizeof(*r->in.$e->{NAME}));"); } else { $self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));"); } } else { $self->pidl("NDR_PULL_ALLOC(ndr, r->out.$e->{NAME});"); if (grep(/in/, @{$e->{DIRECTION}})) { $self->pidl("*r->out.$e->{NAME} = *r->in.$e->{NAME};"); } else { $self->pidl("ZERO_STRUCTP(r->out.$e->{NAME});"); } } } $self->add_deferred(); $self->deindent; $self->pidl("}"); $self->pidl("if (flags & NDR_OUT) {"); $self->indent; $env = GenerateFunctionOutEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { next unless grep(/out/, @{$e->{DIRECTION}}); $self->ParseElementPull($e, "ndr", $env, 1, 1); } if ($fn->{RETURN_TYPE}) { $self->pidl("NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));"); } $self->add_deferred(); $self->deindent; $self->pidl("}"); $self->pidl("return NDR_ERR_SUCCESS;"); $self->deindent; $self->pidl("}"); $self->pidl("");}sub AuthServiceStruct($$$){ my ($self, $ifacename, $authservice) = @_; my @a = split /,/, $authservice; my $authservice_count = $#a + 1; $self->pidl("static const char * const $ifacename\_authservice_strings[] = {"); foreach my $ap (@a) { $self->pidl("\t$ap, "); } $self->pidl("};"); $self->pidl(""); $self->pidl("static const struct ndr_interface_string_array $ifacename\_authservices = {"); $self->pidl("\t.count\t= $authservice_count,"); $self->pidl("\t.names\t= $ifacename\_authservice_strings"); $self->pidl("};"); $self->pidl("");}###################################################################### produce a function call tablesub FunctionTable($$){ my($self,$interface) = @_; my $count = 0; my $uname = uc $interface->{NAME}; return if ($#{$interface->{FUNCTIONS}}+1 == 0); return unless defined ($interface->{PROPERTIES}->{uuid}); $self->pidl("static const struct ndr_interface_call $interface->{NAME}\_calls[] = {"); foreach my $d (@{$interface->{FUNCTIONS}}) { next if not defined($d->{OPNUM}); $self->pidl("\t{"); $self->pidl("\t\t\"$d->{NAME}\","); $self->pidl("\t\tsizeof(struct $d->{NAME}),"); $self->pidl("\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},"); $self->pidl("\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},"); $self->pidl("\t\t(ndr_print_function_t) ndr_print_$d->{NAME},"); $self->pidl("\t\t".($d->{ASYNC}?"true":"false").","); $self->pidl("\t},"); $count++; } $self->pidl("\t{ NULL, 0, NULL, NULL, NULL, false }"); $self->pidl("};"); $self->pidl(""); $self->pidl("static const char * const $interface->{NAME}\_endpoint_strings[] = {"); foreach my $ep (@{$interface->{ENDPOINTS}}) { $self->pidl("\t$ep, "); } my $endpoint_count = $#{$interface->{ENDPOINTS}}+1; $self->pidl("};"); $self->pidl(""); $self->pidl("static const struct ndr_interface_string_array $interface->{NAME}\_endpoints = {"); $self->pidl("\t.count\t= $endpoint_count,"); $self->pidl("\t.names\t= $interface->{NAME}\_endpoint_strings"); $self->pidl("};"); $self->pidl(""); if (! defined $interface->{PROPERTIES}->{authservice}) { $interface->{PROPERTIES}->{authservice} = "\"host\""; } $self->AuthServiceStruct($interface->{NAME}, $interface->{PROPERTIES}->{authservice}); $self->pidl("\nconst struct ndr_interface_table ndr_table_$interface->{NAME} = {"); $self->pidl("\t.name\t\t= \"$interface->{NAME}\","); $self->pidl("\t.syntax_id\t= {"); $self->pidl("\t\t" . print_uuid($interface->{UUID}) .","); $self->pidl("\t\tNDR_$uname\_VERSION"); $self->pidl("\t},"); $self->pidl("\t.helpstring\t= NDR_$uname\_HELPSTRING,"); $self->pidl("\t.num_calls\t= $count,"); $self->pidl("\t.calls\t\t= $interface->{NAME}\_calls,"); $self->pidl("\t.endpoints\t= &$interface->{NAME}\_endpoints,"); $self->pidl("\t.authservices\t= &$interface->{NAME}\_authservices"); $self->pidl("};"); $self->pidl("");}###################################################################### generate include statements for imported idl filessub HeaderImport{ my $self = shift; my @imports = @_; foreach (@imports) { s/\.idl\"$//; s/^\"//; $self->pidl(choose_header("librpc/gen_ndr/ndr_$_\.h", "gen_ndr/ndr_$_.h")); }}###################################################################### generate include statements for included header filessub HeaderInclude{ my $self = shift; my @includes = @_; foreach (@includes) { $self->pidl_hdr("#include $_"); }}###################################################################### generate prototypes and defines for the interface definitions# FIXME: these prototypes are for the DCE/RPC client functions, not the # NDR parser and so do not belong here, technically speakingsub HeaderInterface($$$){ my($self,$interface,$needed) = @_; my $count = 0; if ($needed->{"compression"}) { $self->pidl(choose_header("librpc/ndr/ndr_compression.h", "ndr/compression.h")); } if (has_property($interface, "object")) { $self->pidl(choose_header("librpc/gen_ndr/ndr_orpc.h", "ndr/orpc.h")); } if (defined $interface->{PROPERTIES}->{helper}) { $self->HeaderInclude(split /,/, $interface->{PROPERTIES}->{helper}); } if (defined $interface->{PROPERTIES}->{uuid}) { my $name = uc $interface->{NAME}; $self->pidl_hdr("#define
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?