parser.pm
来自「samba最新软件」· PM 代码 · 共 2,327 行 · 第 1/5 页
PM
2,327 行
} } return $mem_flags;}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 = $self->ParseMemCtxPullFlags($e, $l); return unless defined($mem_c_flags); $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 = $self->ParseMemCtxPullFlags($e, $l); return unless defined($mem_r_flags); $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 = get_array_element($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" and $l->{LEVEL} eq "TOP") { 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 "ref" and $l->{LEVEL} eq "EMBEDDED") { $self->pidl("NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));"); } 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}));"); } else { die("Unhandled pointer type $l->{POINTER_TYPE}"); } $self->pidl("if (_ptr_$e->{NAME}) {"); $self->indent; # 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));"); $self->end_flags($bitmap);}###################################################################### generate a pull function for an bitmapsub ParseBitmapPull($$$){ my($self,$bitmap,$varname) = @_; my $type_fn = $bitmap->{BASE_TYPE}; my($type_decl) = mapTypeName($bitmap->{BASE_TYPE}); $self->pidl("$type_decl v;"); $self->start_flags($bitmap); $self->pidl("NDR_CHECK(ndr_pull_$type_fn(ndr, NDR_SCALARS, &v));"); $self->pidl("*$varname = v;"); $self->end_flags($bitmap);}###################################################################### generate a print function for an bitmapsub ParseBitmapPrintElement($$$$$){ my($self,$e,$bitmap,$name,$varname) = @_; my($type_decl) = mapTypeName($bitmap->{BASE_TYPE}); my($type_fn) = $bitmap->{BASE_TYPE}; my($flag); if ($e =~ /^(\w+) .*$/) { $flag = "$1"; } else { die "Bitmap: \"$name\" invalid Flag: \"$e\""; } $self->pidl("ndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, $varname);");}###################################################################### generate a print function for an bitmapsub ParseBitmapPrint($$$$){ my($self,$bitmap,$name,$varname) = @_; my($type_decl) = mapTypeName($bitmap->{TYPE}); my($type_fn) = $bitmap->{BASE_TYPE}; $self->start_flags($bitmap); $self->pidl("ndr_print_$type_fn(ndr, name, $varname);"); $self->pidl("ndr->depth++;"); foreach my $e (@{$bitmap->{ELEMENTS}}) { $self->ParseBitmapPrintElement($e, $bitmap, $name, $varname); } $self->pidl("ndr->depth--;");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?