📄 parser.pm
字号:
if ($el->{CASE} eq "default") { $have_default = 1; } $self->pidl("$el->{CASE}:"); if ($el->{TYPE} ne "EMPTY") { $self->indent; $self->ParseElementPull($el, "ndr", {$el->{NAME} => "$varname->$el->{NAME}"}, 0, 1); $self->deindent; } $self->pidl("break;"); $self->pidl(""); } if (! $have_default) { $self->pidl("default:"); $self->pidl("\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);"); } $self->deindent; $self->pidl("}");}###################################################################### parse a union - pull sidesub ParseUnionPull($$$){ my ($self,$e,$varname) = @_; my $switch_type = $e->{SWITCH_TYPE}; $self->pidl("int level;"); if (defined($switch_type)) { if (Parse::Pidl::Typelist::typeIs($switch_type, "ENUM")) { $switch_type = Parse::Pidl::Typelist::enum_type_fn(getType($switch_type)->{DATA}); } $self->pidl(mapTypeName($switch_type) . " _level;"); } my %double_cases = (); foreach my $el (@{$e->{ELEMENTS}}) { next if ($el->{TYPE} eq "EMPTY"); next if ($double_cases{"$el->{NAME}"}); $self->DeclareMemCtxVariables($el); $double_cases{"$el->{NAME}"} = 1; } $self->start_flags($e); $self->pidl("level = ndr_pull_get_switch_value(ndr, $varname);"); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; $self->ParseUnionPullPrimitives($e,$varname,$switch_type); $self->deindent; $self->pidl("}"); $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); $self->indent; $self->ParseUnionPullDeferred($e,$varname); $self->deindent; $self->pidl("}"); $self->add_deferred(); $self->end_flags($e);}sub DeclUnion($$$$){ 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,$env,$size) = @_; my $var = ParseExpr($e->{NAME}, $env, $e->{ORIGINAL}); 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("");}###################################################################### 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\""; } my @a = split / /, $interface->{PROPERTIES}->{authservice}; my $authservice_count = $#a + 1; $self->pidl("static const char * const $interface->{NAME}\_authservice_strings[] = {"); foreach my $ap (@a) { $self->pidl("\t$ap, "); } $self->pidl("};"); $self->pidl(""); $self->pidl("static const struct ndr_interface_string_array $interface->{NAME}\_authservices = {"); $self->pidl("\t.count\t= $endpoint_count,"); $self->pidl("\t.names\t= $interface->{NAME}\_authservice_strings"); $self->pidl("};"); $self->pidl(""); $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}\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -