?? parser.pm
字號:
if (ref($l->{DATA_TYPE}) eq "HASH") { $t = "$l->{DATA_TYPE}->{TYPE}_$l->{DATA_TYPE}->{NAME}"; } else { $t = $l->{DATA_TYPE}; } # strings are passed by value rather than reference if (not Parse::Pidl::Typelist::is_scalar($t) or Parse::Pidl::Typelist::scalar_is_reference($t)) { $var_name = get_pointer_to($var_name); } my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); $self->pidl("NDR_CHECK(ndr_push_$t($ndr, $ndr_flags, $var_name));"); } else { $self->ParseTypePush($l->{DATA_TYPE}, $var_name, $primitives, $deferred); }}sub CalcNdrFlags($$$){ my ($l,$primitives,$deferred) = @_; my $scalars = 0; my $buffers = 0; # Add NDR_SCALARS if this one is deferred # and deferreds may be pushed $scalars = 1 if ($l->{IS_DEFERRED} and $deferred); # Add NDR_SCALARS if this one is not deferred and # primitives may be pushed $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives); # Add NDR_BUFFERS if this one contains deferred stuff # and deferreds may be pushed $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred); return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers); return "NDR_SCALARS" if ($scalars); return "NDR_BUFFERS" if ($buffers); return undef;}sub ParseMemCtxPullStart($$$$){ my ($self, $e, $l, $ptr_name) = @_; my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}"; my $mem_c_ctx = $ptr_name; my $mem_c_flags = "0"; return if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED}); if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) { my $nl = GetNextLevel($e, $l); my $next_is_array = ($nl->{TYPE} eq "ARRAY"); my $next_is_string = (($nl->{TYPE} eq "DATA") and ($nl->{DATA_TYPE} eq "string")); if ($next_is_array or $next_is_string) { return; } else { $mem_c_flags = "LIBNDR_FLAG_REF_ALLOC"; } } $self->pidl("$mem_r_ctx = NDR_PULL_GET_MEM_CTX(ndr);"); $self->pidl("NDR_PULL_SET_MEM_CTX(ndr, $mem_c_ctx, $mem_c_flags);");}sub ParseMemCtxPullEnd($$$){ my ($self, $e, $l) = @_; my $mem_r_ctx = "_mem_save_$e->{NAME}_$l->{LEVEL_INDEX}"; my $mem_r_flags = "0"; return if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED}); if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) { my $nl = GetNextLevel($e, $l); my $next_is_array = ($nl->{TYPE} eq "ARRAY"); my $next_is_string = (($nl->{TYPE} eq "DATA") and ($nl->{DATA_TYPE} eq "string")); if ($next_is_array or $next_is_string) { return; } else { $mem_r_flags = "LIBNDR_FLAG_REF_ALLOC"; } } $self->pidl("NDR_PULL_SET_MEM_CTX(ndr, $mem_r_ctx, $mem_r_flags);");}sub CheckStringTerminator($$$$$){ my ($self,$ndr,$e,$l,$length) = @_; my $nl = GetNextLevel($e, $l); # Make sure last element is zero! $self->pidl("NDR_CHECK(ndr_check_string_terminator($ndr, $length, sizeof($nl->{DATA_TYPE}_t)));");}sub ParseElementPullLevel{ my($self,$e,$l,$ndr,$var_name,$env,$primitives,$deferred) = @_; my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); if ($l->{TYPE} eq "ARRAY" and ($l->{IS_VARYING} or $l->{IS_CONFORMANT})) { $var_name = get_pointer_to($var_name); } # Only pull something if there's actually something to be pulled if (defined($ndr_flags)) { if ($l->{TYPE} eq "SUBCONTEXT") { my $subndr = $self->ParseSubcontextPullStart($e, $l, $ndr, $env); $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $subndr, $var_name, $env, 1, 1); $self->ParseSubcontextPullEnd($e, $l, $ndr, $env); } elsif ($l->{TYPE} eq "ARRAY") { my $length = $self->ParseArrayPullHeader($e, $l, $ndr, $var_name, $env); my $nl = GetNextLevel($e, $l); if (is_charset_array($e,$l)) { if ($l->{IS_ZERO_TERMINATED}) { $self->CheckStringTerminator($ndr, $e, $l, $length); } $self->pidl("NDR_CHECK(ndr_pull_charset($ndr, $ndr_flags, ".get_pointer_to($var_name).", $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));"); return; } elsif (has_fast_array($e, $l)) { if ($l->{IS_ZERO_TERMINATED}) { $self->CheckStringTerminator($ndr,$e,$l,$length); } $self->pidl("NDR_CHECK(ndr_pull_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));"); return; } } elsif ($l->{TYPE} eq "POINTER") { $self->ParsePtrPull($e, $l, $ndr, $var_name); } elsif ($l->{TYPE} eq "SWITCH") { $self->ParseSwitchPull($e, $l, $ndr, $var_name, $env); } elsif ($l->{TYPE} eq "DATA") { $self->ParseDataPull($e, $l, $ndr, $var_name, $primitives, $deferred); } } # add additional constructions if ($l->{TYPE} eq "POINTER" and $deferred) { if ($l->{POINTER_TYPE} ne "ref") { $self->pidl("if ($var_name) {"); $self->indent; if ($l->{POINTER_TYPE} eq "relative") { $self->pidl("uint32_t _relative_save_offset;"); $self->pidl("_relative_save_offset = ndr->offset;"); $self->pidl("NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));"); } } $self->ParseMemCtxPullStart($e, $l, $var_name); $var_name = get_value_of($var_name); $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 1); $self->ParseMemCtxPullEnd($e,$l); if ($l->{POINTER_TYPE} ne "ref") { if ($l->{POINTER_TYPE} eq "relative") { $self->pidl("ndr->offset = _relative_save_offset;"); } $self->deindent; $self->pidl("}"); } } elsif ($l->{TYPE} eq "ARRAY" and not has_fast_array($e,$l) and not is_charset_array($e, $l)) { my $length = ParseExpr($l->{LENGTH_IS}, $env, $e->{ORIGINAL}); my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; my $array_name = $var_name; $var_name = $var_name . "[$counter]"; $self->ParseMemCtxPullStart($e, $l, $array_name); if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) { my $nl = GetNextLevel($e,$l); if ($l->{IS_ZERO_TERMINATED}) { $self->CheckStringTerminator($ndr,$e,$l,$length); } $self->pidl("for ($counter = 0; $counter < $length; $counter++) {"); $self->indent; $self->ParseElementPullLevel($e, $nl, $ndr, $var_name, $env, 1, 0); $self->deindent; $self->pidl("}"); } if ($deferred and ContainsDeferred($e, $l)) { $self->pidl("for ($counter = 0; $counter < $length; $counter++) {"); $self->indent; $self->ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1); $self->deindent; $self->pidl("}"); } $self->ParseMemCtxPullEnd($e, $l); } elsif ($l->{TYPE} eq "SWITCH") { $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); }}###################################################################### parse scalars in a structure element - pull sizesub ParseElementPull($$$$$$){ my($self,$e,$ndr,$env,$primitives,$deferred) = @_; my $var_name = $env->{$e->{NAME}}; my $represent_name; my $transmit_name; return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0])); if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { $self->pidl("{"); $self->indent; $represent_name = $var_name; $transmit_name = "_transmit_$e->{NAME}"; $var_name = $transmit_name; $self->pidl(mapTypeName($e->{TYPE})." $var_name;"); } $var_name = append_prefix($e, $var_name); $self->start_flags($e); $self->ParseElementPullLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred); $self->end_flags($e); # Representation type is different from transmit_as if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { $self->pidl("NDR_CHECK(ndr_$e->{TYPE}_to_$e->{REPRESENTATION_TYPE}($transmit_name, ".get_pointer_to($represent_name)."));"); $self->deindent; $self->pidl("}"); }}###################################################################### parse a pointer in a struct element or functionsub ParsePtrPull($$$$$){ my($self, $e,$l,$ndr,$var_name) = @_; my $nl = GetNextLevel($e, $l); my $next_is_array = ($nl->{TYPE} eq "ARRAY"); my $next_is_string = (($nl->{TYPE} eq "DATA") and ($nl->{DATA_TYPE} eq "string")); if ($l->{POINTER_TYPE} eq "ref") { if ($l->{LEVEL} eq "EMBEDDED") { $self->pidl("NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));"); } if (!$next_is_array and !$next_is_string) { $self->pidl("if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); $self->pidl("\tNDR_PULL_ALLOC($ndr, $var_name);"); $self->pidl("}"); } return; } elsif (($l->{POINTER_TYPE} eq "unique") or ($l->{POINTER_TYPE} eq "relative") or ($l->{POINTER_TYPE} eq "full")) { $self->pidl("NDR_CHECK(ndr_pull_generic_ptr($ndr, &_ptr_$e->{NAME}));"); $self->pidl("if (_ptr_$e->{NAME}) {"); $self->indent; } else { die("Unhandled pointer type $l->{POINTER_TYPE}"); } # Don't do this for arrays, they're allocated at the actual level # of the array unless ($next_is_array or $next_is_string) { $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);"); } else { # FIXME: Yes, this is nasty. # We allocate an array twice # - once just to indicate that it's there, # - then the real allocation... $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);"); } #$self->pidl("memset($var_name, 0, sizeof($var_name));"); if ($l->{POINTER_TYPE} eq "relative") { $self->pidl("NDR_CHECK(ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME}));"); } $self->deindent; $self->pidl("} else {"); $self->pidl("\t$var_name = NULL;"); $self->pidl("}");}sub ParseStructPushPrimitives($$$$){ my ($self, $struct, $varname, $env) = @_; # see if the structure contains a conformant array. If it # does, then it must be the last element of the structure, and # we need to push the conformant length early, as it fits on # the wire before the structure (and even before the structure # alignment) if (defined($struct->{SURROUNDING_ELEMENT})) { my $e = $struct->{SURROUNDING_ELEMENT}; if (defined($e->{LEVELS}[0]) and $e->{LEVELS}[0]->{TYPE} eq "ARRAY") { my $size; if ($e->{LEVELS}[0]->{IS_ZERO_TERMINATED}) { if (has_property($e, "charset")) { $size = "ndr_charset_length($varname->$e->{NAME}, CH_$e->{PROPERTIES}->{charset})"; } else { $size = "ndr_string_length($varname->$e->{NAME}, sizeof(*$varname->$e->{NAME}))"; } } else { $size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL}); } $self->pidl("NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));"); } else { $self->pidl("NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, $varname->$e->{NAME})));"); } } $self->pidl("NDR_CHECK(ndr_push_align(ndr, $struct->{ALIGN}));"); if (defined($struct->{PROPERTIES}{relative_base})) { # set the current offset as base for relative pointers # and store it based on the toplevel struct/union $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset1(ndr, $varname, ndr->offset));"); } $self->ParseElementPush($_, "ndr", $env, 1, 0) foreach (@{$struct->{ELEMENTS}});}sub ParseStructPushDeferred($$$){ my ($self, $struct, $varname, $env) = @_; if (defined($struct->{PROPERTIES}{relative_base})) { # retrieve the current offset as base for relative pointers # based on the toplevel struct/union $self->pidl("NDR_CHECK(ndr_push_setup_relative_base_offset2(ndr, $varname));"); } $self->ParseElementPush($_, "ndr", $env, 0, 1) foreach (@{$struct->{ELEMENTS}});}###################################################################### parse a structsub ParseStructPush($$$){ my ($self, $struct, $varname) = @_; return unless defined($struct->{ELEMENTS}); my $env = GenerateStructEnv($struct, $varname); EnvSubstituteValue($env, $struct); $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}}); $self->start_flags($struct); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; $self->ParseStructPushPrimitives($struct, $varname, $env); $self->deindent; $self->pidl("}"); $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); $self->indent; $self->ParseStructPushDeferred($struct, $varname, $env); $self->deindent; $self->pidl("}"); $self->end_flags($struct);}###################################################################### generate a push function for an enumsub ParseEnumPush($$$){ my($self,$enum,$varname) = @_; my($type_fn) = $enum->{BASE_TYPE}; $self->start_flags($enum); $self->pidl("NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, $varname));"); $self->end_flags($enum);}###################################################################### generate a pull function for an enumsub ParseEnumPull($$$){ my($self,$enum,$varname) = @_; my($type_fn) = $enum->{BASE_TYPE}; my($type_v_decl) = mapTypeName($type_fn); $self->pidl("$type_v_decl v;"); $self->start_flags($enum); $self->pidl("NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));"); $self->pidl("*$varname = v;"); $self->end_flags($enum);}###################################################################### generate a print function for an enumsub ParseEnumPrint($$$$){ my($self,$enum,$name,$varname) = @_; $self->pidl("const char *val = NULL;"); $self->pidl(""); $self->start_flags($enum); $self->pidl("switch ($varname) {"); $self->indent; my $els = \@{$enum->{ELEMENTS}}; foreach my $i (0 .. $#{$els}) { my $e = ${$els}[$i]; chomp $e; if ($e =~ /^(.*)=/) { $e = $1; } $self->pidl("case $e: val = \"$e\"; break;"); } $self->deindent; $self->pidl("}"); $self->pidl("ndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, $varname);"); $self->end_flags($enum);}sub DeclEnum($$$$){ my ($e,$t,$name,$varname) = @_; return "enum $name " . ($t eq "pull"?"*":"") . $varname;}$typefamily{ENUM} = { DECL => \&DeclEnum, PUSH_FN_BODY => \&ParseEnumPush, PULL_FN_BODY => \&ParseEnumPull, PRINT_FN_BODY => \&ParseEnumPrint,};###################################################################### generate a push function for a bitmapsub ParseBitmapPush($$$){ my($self,$bitmap,$varname) = @_; my($type_fn) = $bitmap->{BASE_TYPE}; $self->start_flags($bitmap); $self->pidl("NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, $varname));");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -