parser.pm

来自「samba最新软件」· PM 代码 · 共 2,327 行 · 第 1/5 页

PM
2,327
字号
	my $subndr = "_ndr_$e->{NAME}";	my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE}, $env, $e->{ORIGINAL});	$self->pidl("{");	$self->indent;	$self->pidl("struct ndr_push *$subndr;");	$self->pidl("NDR_CHECK(ndr_push_subcontext_start($ndr, &$subndr, $l->{HEADER_SIZE}, $subcontext_size));");	if (defined $l->{COMPRESSION}) {		$subndr = $self->ParseCompressionPushStart($e, $l, $subndr, $env);	}	return $subndr;}sub ParseSubcontextPushEnd($$$$$){	my ($self,$e,$l,$ndr,$env) = @_;	my $subndr = "_ndr_$e->{NAME}";	my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE}, $env, $e->{ORIGINAL});	if (defined $l->{COMPRESSION}) {		$self->ParseCompressionPushEnd($e, $l, $subndr, $env);	}	$self->pidl("NDR_CHECK(ndr_push_subcontext_end($ndr, $subndr, $l->{HEADER_SIZE}, $subcontext_size));");	$self->deindent;	$self->pidl("}");}sub ParseSubcontextPullStart($$$$$){	my ($self,$e,$l,$ndr,$env) = @_;	my $subndr = "_ndr_$e->{NAME}";	my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE}, $env, $e->{ORIGINAL});	$self->pidl("{");	$self->indent;	$self->pidl("struct ndr_pull *$subndr;");	$self->pidl("NDR_CHECK(ndr_pull_subcontext_start($ndr, &$subndr, $l->{HEADER_SIZE}, $subcontext_size));");	if (defined $l->{COMPRESSION}) {		$subndr = $self->ParseCompressionPullStart($e, $l, $subndr, $env);	}	return $subndr;}sub ParseSubcontextPullEnd($$$$$){	my ($self,$e,$l,$ndr,$env) = @_;	my $subndr = "_ndr_$e->{NAME}";	my $subcontext_size = ParseExpr($l->{SUBCONTEXT_SIZE}, $env, $e->{ORIGINAL});	if (defined $l->{COMPRESSION}) {		$self->ParseCompressionPullEnd($e, $l, $subndr, $env);	}	$self->pidl("NDR_CHECK(ndr_pull_subcontext_end($ndr, $subndr, $l->{HEADER_SIZE}, $subcontext_size));");	$self->deindent;	$self->pidl("}");}sub ParseElementPushLevel{	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_CONFORMANT} or $l->{IS_VARYING})) {		$var_name = get_pointer_to($var_name);	}	if (defined($ndr_flags)) {		if ($l->{TYPE} eq "SUBCONTEXT") {			my $subndr = $self->ParseSubcontextPushStart($e, $l, $ndr, $env);			$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $subndr, $var_name, $env, 1, 1);			$self->ParseSubcontextPushEnd($e, $l, $ndr, $env);		} elsif ($l->{TYPE} eq "POINTER") {			$self->ParsePtrPush($e, $l, $var_name);		} elsif ($l->{TYPE} eq "ARRAY") {			my $length = $self->ParseArrayPushHeader($e, $l, $ndr, $var_name, $env); 			my $nl = GetNextLevel($e, $l);			# Allow speedups for arrays of scalar types			if (is_charset_array($e,$l)) {				$self->pidl("NDR_CHECK(ndr_push_charset($ndr, $ndr_flags, $var_name, $length, sizeof(" . mapTypeName($nl->{DATA_TYPE}) . "), CH_$e->{PROPERTIES}->{charset}));");				return;			} elsif (has_fast_array($e,$l)) {				$self->pidl("NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));");				return;			} 		} elsif ($l->{TYPE} eq "SWITCH") {			$self->ParseSwitchPush($e, $l, $ndr, $var_name, $env);		} elsif ($l->{TYPE} eq "DATA") {			$self->ParseDataPush($e, $l, $ndr, $var_name, $primitives, $deferred);		}	}	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("NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_name));");			}		}		$var_name = get_value_of($var_name);		$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1);		if ($l->{POINTER_TYPE} ne "ref") {			$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}";		$var_name = get_array_element($var_name, $counter);		if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) {			$self->pidl("for ($counter = 0; $counter < $length; $counter++) {");			$self->indent;			$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $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->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1);			$self->deindent;			$self->pidl("}");		}		} elsif ($l->{TYPE} eq "SWITCH") {		$self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred);	}}###################################################################### parse scalars in a structure elementsub ParseElementPush($$$$$$){	my ($self,$e,$ndr,$env,$primitives,$deferred) = @_;	my $subndr = undef;	my $var_name = $env->{$e->{NAME}};	return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0]));	# Representation type is different from transmit_as	if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {		$self->pidl("{");		$self->indent;		my $transmit_name = "_transmit_$e->{NAME}";		$self->pidl(mapTypeName($e->{TYPE}) ." $transmit_name;");		$self->pidl("NDR_CHECK(ndr_$e->{REPRESENTATION_TYPE}_to_$e->{TYPE}($var_name, " . get_pointer_to($transmit_name) . "));");		$var_name = $transmit_name;	}	$var_name = append_prefix($e, $var_name);	$self->start_flags($e);	if (defined(my $value = has_property($e, "value"))) {		$var_name = ParseExpr($value, $env, $e->{ORIGINAL});	}	$self->ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $var_name, $env, $primitives, $deferred);	$self->end_flags($e);	if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {		$self->deindent;		$self->pidl("}");	}}###################################################################### parse a pointer in a struct element or functionsub ParsePtrPush($$$$){	my ($self,$e,$l,$var_name) = @_;	if ($l->{POINTER_TYPE} eq "ref") {		$self->pidl("if ($var_name == NULL) {");		$self->indent;		$self->pidl("return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL [ref] pointer\");");		$self->deindent;		$self->pidl("}");		if ($l->{LEVEL} eq "EMBEDDED") {			$self->pidl("NDR_CHECK(ndr_push_ref_ptr(ndr));");		}	} elsif ($l->{POINTER_TYPE} eq "relative") {		$self->pidl("NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_name));");	} elsif ($l->{POINTER_TYPE} eq "unique") {		$self->pidl("NDR_CHECK(ndr_push_unique_ptr(ndr, $var_name));");	} elsif ($l->{POINTER_TYPE} eq "full") {		$self->pidl("NDR_CHECK(ndr_push_full_ptr(ndr, $var_name));");	} else {		die("Unhandled pointer type $l->{POINTER_TYPE}");	}}sub need_pointer_to($$$){	my ($e, $l, $scalar_only) = @_;	my $t;	if (ref($l->{DATA_TYPE})) {		$t = "$l->{DATA_TYPE}->{TYPE}_$l->{DATA_TYPE}->{NAME}";	} else {		$t = $l->{DATA_TYPE};	}	if (not Parse::Pidl::Typelist::is_scalar($t)) {		return 1 if $scalar_only;	}	my $arrays = 0;	foreach my $tl (@{$e->{LEVELS}}) {		last if $l == $tl;		if ($tl->{TYPE} eq "ARRAY") {			$arrays++;		}	}	if (Parse::Pidl::Typelist::scalar_is_reference($t)) {		return 1 unless $arrays;	}	return 0;}sub ParseDataPrint($$$$){	my ($self, $e, $l, $var_name) = @_;		if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) {		if (need_pointer_to($e, $l, 1)) {			$var_name = get_pointer_to($var_name);		}		$self->pidl(TypeFunctionName("ndr_print", $l->{DATA_TYPE})."(ndr, \"$e->{NAME}\", $var_name);");	} else {		$self->ParseTypePrint($l->{DATA_TYPE}, $var_name);	}}###################################################################### print scalars in a structure elementsub ParseElementPrint($$$$){	my($self, $e, $var_name, $env) = @_;	return if (has_property($e, "noprint"));	if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) {		$self->pidl("ndr_print_$e->{REPRESENTATION_TYPE}(ndr, \"$e->{NAME}\", $var_name);");		return;	}	$var_name = append_prefix($e, $var_name);	if (defined(my $value = has_property($e, "value"))) {		$var_name = "(ndr->flags & LIBNDR_PRINT_SET_VALUES)?" . ParseExpr($value,$env, $e->{ORIGINAL}) . ":$var_name";	}	foreach my $l (@{$e->{LEVELS}}) {		if ($l->{TYPE} eq "POINTER") {			$self->pidl("ndr_print_ptr(ndr, \"$e->{NAME}\", $var_name);");			$self->pidl("ndr->depth++;");			if ($l->{POINTER_TYPE} ne "ref") {				$self->pidl("if ($var_name) {");				$self->indent;			}			$var_name = get_value_of($var_name);		} elsif ($l->{TYPE} eq "ARRAY") {			my $length;			if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) {				$var_name = get_pointer_to($var_name); 			}						if ($l->{IS_ZERO_TERMINATED}) {				$length = "ndr_string_length($var_name, sizeof(*$var_name))";			} else {				$length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, 							check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return;"), check_fully_dereferenced($e, $env));			}			if (is_charset_array($e,$l)) {				$self->pidl("ndr_print_string(ndr, \"$e->{NAME}\", $var_name);");				last;			} elsif (has_fast_array($e, $l)) {				my $nl = GetNextLevel($e, $l);				$self->pidl("ndr_print_array_$nl->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);");				last;			} else {				my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";				$self->pidl("ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);");				$self->pidl("ndr->depth++;");				$self->pidl("for ($counter=0;$counter<$length;$counter++) {");				$self->indent;				$self->pidl("char *idx_$l->{LEVEL_INDEX}=NULL;");				$self->pidl("if (asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter) != -1) {");				$self->indent;				$var_name = get_array_element($var_name, $counter);			}		} elsif ($l->{TYPE} eq "DATA") {			$self->ParseDataPrint($e, $l, $var_name);		} elsif ($l->{TYPE} eq "SWITCH") {			my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, 						check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return;"), check_fully_dereferenced($e, $env));			$self->pidl("ndr_print_set_switch_value(ndr, " . get_pointer_to($var_name) . ", $switch_var);");		} 	}	foreach my $l (reverse @{$e->{LEVELS}}) {		if ($l->{TYPE} eq "POINTER") {			if ($l->{POINTER_TYPE} ne "ref") {				$self->deindent;				$self->pidl("}");			}			$self->pidl("ndr->depth--;");		} elsif (($l->{TYPE} eq "ARRAY")			and not is_charset_array($e,$l)			and not has_fast_array($e,$l)) {			$self->pidl("free(idx_$l->{LEVEL_INDEX});");			$self->deindent;			$self->pidl("}");			$self->deindent;			$self->pidl("}");			$self->pidl("ndr->depth--;");		}	}}###################################################################### parse scalars in a structure element - pull sizesub ParseSwitchPull($$$$$$){	my($self,$e,$l,$ndr,$var_name,$env) = @_;	my $switch_var = ParseExprExt($l->{SWITCH_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 switch_is()\");"),		check_fully_dereferenced($e, $env));	$var_name = get_pointer_to($var_name);	$self->pidl("NDR_CHECK(ndr_pull_set_switch_value($ndr, $var_name, $switch_var));");}###################################################################### push switch elementsub ParseSwitchPush($$$$$$){	my($self,$e,$l,$ndr,$var_name,$env) = @_;	my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, 		check_null_pointer($e, $env, sub { $self->pidl(shift); },				   "return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"),		check_fully_dereferenced($e, $env));	$var_name = get_pointer_to($var_name);	$self->pidl("NDR_CHECK(ndr_push_set_switch_value($ndr, $var_name, $switch_var));");}sub ParseDataPull($$$$$$$){	my ($self,$e,$l,$ndr,$var_name,$primitives,$deferred) = @_;	if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) {		my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);		if (need_pointer_to($e, $l, 0)) {			$var_name = get_pointer_to($var_name);		}		$var_name = get_pointer_to($var_name);		$self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");		if (my $range = has_property($e, "range")) {			$var_name = get_value_of($var_name);			my ($low, $high) = split(/,/, $range, 2);			$self->pidl("if ($var_name < $low || $var_name > $high) {");			$self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");");			$self->pidl("}");		}	} else {		$self->ParseTypePull($l->{DATA_TYPE}, $var_name, $primitives, $deferred);	}}sub ParseDataPush($$$$$$$){	my ($self,$e,$l,$ndr,$var_name,$primitives,$deferred) = @_;	if (not ref($l->{DATA_TYPE}) or defined($l->{DATA_TYPE}->{NAME})) {		my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred);		# strings are passed by value rather than reference		if (need_pointer_to($e, $l, 1)) {			$var_name = get_pointer_to($var_name);		}		$self->pidl("NDR_CHECK(".TypeFunctionName("ndr_push", $l->{DATA_TYPE})."($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 ParseMemCtxPullFlags($$$$){	my ($self, $e, $l) = @_;	return undef unless ($l->{TYPE} eq "POINTER" or $l->{TYPE} eq "ARRAY");	return undef if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED});	return undef if has_fast_array($e, $l);	return undef if is_charset_array($e, $l);	my $mem_flags = "0";	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 undef;		} elsif ($l->{LEVEL} eq "TOP") {			$mem_flags = "LIBNDR_FLAG_REF_ALLOC";

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?