⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ndr.pm

📁 wireshark 0.99.7 最新源码
💻 PM
📖 第 1 页 / 共 2 页
字号:
#################################################### Samba4 NDR info tree generator# Copyright tridge@samba.org 2000-2003# Copyright tpot@samba.org 2001# Copyright jelmer@samba.org 2004-2006# released under the GNU GPL=pod=head1 NAMEParse::Pidl::NDR - NDR parsing information generator=head1 DESCRIPTIONReturn a table describing the order in which the parts of an elementshould be parsedPossible level types: - POINTER - ARRAY - SUBCONTEXT - SWITCH - DATA=head1 AUTHORJelmer Vernooij <jelmer@samba.org>=cutpackage Parse::Pidl::NDR;require Exporter;use vars qw($VERSION);$VERSION = '0.01';@ISA = qw(Exporter);@EXPORT = qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsString);@EXPORT_OK = qw(GetElementLevelTable ParseElement ValidElement align_type mapToScalar ParseType can_contain_deferred);use strict;use Parse::Pidl qw(warning fatal);use Parse::Pidl::Typelist qw(hasType getType expandAlias);use Parse::Pidl::Util qw(has_property property_matches);# Alignment of the built-in scalar typesmy $scalar_alignment = {	'void' => 0,	'char' => 1,	'int8' => 1,	'uint8' => 1,	'int16' => 2,	'uint16' => 2,	'int32' => 4,	'uint32' => 4,	'hyper' => 8,	'pointer' => 8,	'dlong' => 4,	'udlong' => 4,	'udlongr' => 4,	'DATA_BLOB' => 4,	'string' => 4,	'string_array' => 4, #???	'time_t' => 4,	'NTTIME' => 4,	'NTTIME_1sec' => 4,	'NTTIME_hyper' => 8,	'WERROR' => 4,	'NTSTATUS' => 4,	'COMRESULT' => 4,	'nbt_string' => 4,	'wrepl_nbt_name' => 4,	'ipv4address' => 4};sub GetElementLevelTable($){	my $e = shift;	my $order = [];	my $is_deferred = 0;	my @bracket_array = ();	my @length_is = ();	my @size_is = ();	my $pointer_idx = 0;	if (has_property($e, "size_is")) {		@size_is = split /,/, has_property($e, "size_is");	}	if (has_property($e, "length_is")) {		@length_is = split /,/, has_property($e, "length_is");	}	if (defined($e->{ARRAY_LEN})) {		@bracket_array = @{$e->{ARRAY_LEN}};	}	if (has_property($e, "out")) {		my $needptrs = 1;		if (has_property($e, "string")) { $needptrs++; }		if ($#bracket_array >= 0) { $needptrs = 0; }		warning($e, "[out] argument `$e->{NAME}' not a pointer") if ($needptrs > $e->{POINTERS});	}	# Parse the [][][][] style array stuff	for my $i (0 .. $#bracket_array) {		my $d = $bracket_array[$#bracket_array - $i];		my $size = $d;		my $length = $d;		my $is_surrounding = 0;		my $is_varying = 0;		my $is_conformant = 0;		my $is_string = 0;		my $is_fixed = 0;		my $is_inline = 0;		if ($d eq "*") {			$is_conformant = 1;			if ($size = shift @size_is) {			} elsif ((scalar(@size_is) == 0) and has_property($e, "string")) {				$is_string = 1;				delete($e->{PROPERTIES}->{string});			} else {				fatal($e, "Must specify size_is() for conformant array!")			}			if (($length = shift @length_is) or $is_string) {				$is_varying = 1;			} else {				$length = $size;			}			if ($e == $e->{PARENT}->{ELEMENTS}[-1] 				and $e->{PARENT}->{TYPE} ne "FUNCTION") {				$is_surrounding = 1;			}		}		$is_fixed = 1 if (not $is_conformant and Parse::Pidl::Util::is_constant($size));		$is_inline = 1 if (not $is_conformant and not Parse::Pidl::Util::is_constant($size));		push (@$order, {			TYPE => "ARRAY",			SIZE_IS => $size,			LENGTH_IS => $length,			IS_DEFERRED => $is_deferred,			IS_SURROUNDING => $is_surrounding,			IS_ZERO_TERMINATED => $is_string,			IS_VARYING => $is_varying,			IS_CONFORMANT => $is_conformant,			IS_FIXED => $is_fixed,			IS_INLINE => $is_inline		});	}	# Next, all the pointers	foreach my $i (1..$e->{POINTERS}) {		my $pt = pointer_type($e);		my $level = "EMBEDDED";		# Top level "ref" pointers do not have a referrent identifier		$level = "TOP" if ( defined($pt) 				and $i == 1				and $e->{PARENT}->{TYPE} eq "FUNCTION");		push (@$order, { 			TYPE => "POINTER",			# for now, there can only be one pointer type per element			POINTER_TYPE => pointer_type($e),			POINTER_INDEX => $pointer_idx,			IS_DEFERRED => "$is_deferred",			LEVEL => $level		});		warning($e, "top-level \[out\] pointer `$e->{NAME}' is not a \[ref\] pointer") 			if ($i == 1 and pointer_type($e) ne "ref" and 				$e->{PARENT}->{TYPE} eq "FUNCTION" and 				not has_property($e, "in"));		$pointer_idx++;				# everything that follows will be deferred		$is_deferred = 1 if ($e->{PARENT}->{TYPE} ne "FUNCTION");		my $array_size = shift @size_is;		my $array_length;		my $is_varying;		my $is_conformant;		my $is_string = 0;		if ($array_size) {			$is_conformant = 1;			if ($array_length = shift @length_is) {				$is_varying = 1;			} else {				$array_length = $array_size;				$is_varying =0;			}		} 				if (scalar(@size_is) == 0 and has_property($e, "string") and 		    $i == $e->{POINTERS}) {			$is_string = 1;			$is_varying = $is_conformant = has_property($e, "noheader")?0:1;			delete($e->{PROPERTIES}->{string});		}		if ($array_size or $is_string) {			push (@$order, {				TYPE => "ARRAY",				SIZE_IS => $array_size,				LENGTH_IS => $array_length,				IS_DEFERRED => $is_deferred,				IS_SURROUNDING => 0,				IS_ZERO_TERMINATED => $is_string,				IS_VARYING => $is_varying,				IS_CONFORMANT => $is_conformant,				IS_FIXED => 0,				IS_INLINE => 0			});			$is_deferred = 0;		} 	}	if (defined(has_property($e, "subcontext"))) {		my $hdr_size = has_property($e, "subcontext");		my $subsize = has_property($e, "subcontext_size");		if (not defined($subsize)) { 			$subsize = -1; 		}				push (@$order, {			TYPE => "SUBCONTEXT",			HEADER_SIZE => $hdr_size,			SUBCONTEXT_SIZE => $subsize,			IS_DEFERRED => $is_deferred,			COMPRESSION => has_property($e, "compression"),		});	}	if (my $switch = has_property($e, "switch_is")) {		push (@$order, {			TYPE => "SWITCH", 			SWITCH_IS => $switch,			IS_DEFERRED => $is_deferred		});	}	if (scalar(@size_is) > 0) {		fatal($e, "size_is() on non-array element");	}	if (scalar(@length_is) > 0) {		fatal($e, "length_is() on non-array element");	}	if (has_property($e, "string")) {		fatal($e, "string() attribute on non-array element");	}	push (@$order, {		TYPE => "DATA",		DATA_TYPE => $e->{TYPE},		IS_DEFERRED => $is_deferred,		CONTAINS_DEFERRED => can_contain_deferred($e->{TYPE}),		IS_SURROUNDING => 0 #FIXME	});	my $i = 0;	foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; }	return $order;}###################################################################### see if a type contains any deferred data sub can_contain_deferred($){	sub can_contain_deferred($);	my ($type) = @_;	return 1 unless (hasType($type)); # assume the worst	$type = getType($type);	return 0 if (Parse::Pidl::Typelist::is_scalar($type));	return 1 if ($type->{TYPE} eq "DECLARE"); # assume the worst	return can_contain_deferred($type->{DATA}) if ($type->{TYPE} eq "TYPEDEF");	return 0 unless defined($type->{ELEMENTS});	foreach (@{$type->{ELEMENTS}}) {		return 1 if ($_->{POINTERS});		return 1 if (can_contain_deferred ($_->{TYPE}));	}		return 0;}sub pointer_type($){	my $e = shift;	return undef unless $e->{POINTERS};		return "ref" if (has_property($e, "ref"));	return "full" if (has_property($e, "ptr"));	return "sptr" if (has_property($e, "sptr"));	return "unique" if (has_property($e, "unique"));	return "relative" if (has_property($e, "relative"));	return "ignore" if (has_property($e, "ignore"));	return undef;}###################################################################### work out the correct alignment for a structure or unionsub find_largest_alignment($){	my $s = shift;	my $align = 1;	for my $e (@{$s->{ELEMENTS}}) {		my $a = 1;		if ($e->{POINTERS}) {			$a = 4; 		} elsif (has_property($e, "subcontext")) { 			$a = 1;		} elsif (has_property($e, "transmit_as")) {			$a = align_type($e->{PROPERTIES}->{transmit_as});		} else {			$a = align_type($e->{TYPE}); 		}		$align = $a if ($align < $a);	}	return $align;}###################################################################### align a typesub align_type($){	sub align_type($);	my ($e) = @_;	if (ref($e) eq "HASH" and $e->{TYPE} eq "SCALAR") {		return $scalar_alignment->{$e->{NAME}};	}	unless (hasType($e)) {	    # it must be an external type - all we can do is guess 		# print "Warning: assuming alignment of unknown type '$e' is 4\n";	    return 4;	}	my $dt = getType($e);	if ($dt->{TYPE} eq "TYPEDEF" or $dt->{TYPE} eq "DECLARE") {		return align_type($dt->{DATA});	} elsif ($dt->{TYPE} eq "ENUM") {		return align_type(Parse::Pidl::Typelist::enum_type_fn($dt));	} elsif ($dt->{TYPE} eq "BITMAP") {		return align_type(Parse::Pidl::Typelist::bitmap_type_fn($dt));	} elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) {		return find_largest_alignment($dt);	}	die("Unknown data type type $dt->{TYPE}");}sub ParseElement($$){	my ($e, $pointer_default) = @_;	$e->{TYPE} = expandAlias($e->{TYPE});	if (ref($e->{TYPE}) eq "HASH") {		$e->{TYPE} = ParseType($e->{TYPE}, $pointer_default);	}	return {		NAME => $e->{NAME},		TYPE => $e->{TYPE},		PROPERTIES => $e->{PROPERTIES},		LEVELS => GetElementLevelTable($e),		REPRESENTATION_TYPE => ($e->{PROPERTIES}->{represent_as} or $e->{TYPE}),		ALIGN => align_type($e->{TYPE}),		ORIGINAL => $e	};}sub ParseStruct($$){	my ($struct, $pointer_default) = @_;	my @elements = ();	my $surrounding = undef;	return {		TYPE => "STRUCT",		NAME => $struct->{NAME},		SURROUNDING_ELEMENT => undef,		ELEMENTS => undef,		PROPERTIES => $struct->{PROPERTIES},		ORIGINAL => $struct,		ALIGN => undef	} unless defined($struct->{ELEMENTS});	CheckPointerTypes($struct, $pointer_default);	foreach my $x (@{$struct->{ELEMENTS}}) 	{		my $e = ParseElement($x, $pointer_default);		if ($x != $struct->{ELEMENTS}[-1] and 			$e->{LEVELS}[0]->{IS_SURROUNDING}) {			fatal($x, "conformant member not at end of struct");		}		push @elements, $e;	}	my $e = $elements[-1];	if (defined($e) and defined($e->{LEVELS}[0]->{IS_SURROUNDING}) and		$e->{LEVELS}[0]->{IS_SURROUNDING}) {		$surrounding = $e;	}	if (defined $e->{TYPE} && $e->{TYPE} eq "string"	    &&  property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {		$surrounding = $struct->{ELEMENTS}[-1];	}	my $align = undef;	if ($struct->{NAME}) {		$align = align_type($struct->{NAME});	}			return {		TYPE => "STRUCT",		NAME => $struct->{NAME},		SURROUNDING_ELEMENT => $surrounding,		ELEMENTS => \@elements,		PROPERTIES => $struct->{PROPERTIES},		ORIGINAL => $struct,		ALIGN => $align	};}sub ParseUnion($$){	my ($e, $pointer_default) = @_;	my @elements = ();	my $hasdefault = 0;	my $switch_type = has_property($e, "switch_type");	unless (defined($switch_type)) { $switch_type = "uint32"; }	if (has_property($e, "nodiscriminant")) { $switch_type = undef; }	return {		TYPE => "UNION",		NAME => $e->{NAME},		SWITCH_TYPE => $switch_type,		ELEMENTS => undef,		PROPERTIES => $e->{PROPERTIES},		HAS_DEFAULT => $hasdefault,		ORIGINAL => $e	} unless defined($e->{ELEMENTS});	CheckPointerTypes($e, $pointer_default);	foreach my $x (@{$e->{ELEMENTS}}) 	{		my $t;		if ($x->{TYPE} eq "EMPTY") {			$t = { TYPE => "EMPTY" };		} else {			$t = ParseElement($x, $pointer_default);		}		if (has_property($x, "default")) {			$t->{CASE} = "default";			$hasdefault = 1;		} elsif (defined($x->{PROPERTIES}->{case})) {			$t->{CASE} = "case $x->{PROPERTIES}->{case}";		} else {			die("Union element $x->{NAME} has neither default nor case property");		}		push @elements, $t;	}	return {		TYPE => "UNION",		NAME => $e->{NAME},		SWITCH_TYPE => $switch_type,		ELEMENTS => \@elements,		PROPERTIES => $e->{PROPERTIES},		HAS_DEFAULT => $hasdefault,		ORIGINAL => $e	};}sub ParseEnum($$){	my ($e, $pointer_default) = @_;	return {		TYPE => "ENUM",		NAME => $e->{NAME},		BASE_TYPE => Parse::Pidl::Typelist::enum_type_fn($e),		ELEMENTS => $e->{ELEMENTS},		PROPERTIES => $e->{PROPERTIES},		ORIGINAL => $e	};}sub ParseBitmap($$){	my ($e, $pointer_default) = @_;	return {		TYPE => "BITMAP",		NAME => $e->{NAME},		BASE_TYPE => Parse::Pidl::Typelist::bitmap_type_fn($e),		ELEMENTS => $e->{ELEMENTS},		PROPERTIES => $e->{PROPERTIES},		ORIGINAL => $e	};}sub ParseType($$){	my ($d, $pointer_default) = @_;	my $data = {		STRUCT => \&ParseStruct,		UNION => \&ParseUnion,		ENUM => \&ParseEnum,		BITMAP => \&ParseBitmap,		TYPEDEF => \&ParseTypedef,	}->{$d->{TYPE}}->($d, $pointer_default);	return $data;}sub ParseTypedef($$){	my ($d, $pointer_default) = @_;	if (defined($d->{DATA}->{PROPERTIES}) && !defined($d->{PROPERTIES})) {		$d->{PROPERTIES} = $d->{DATA}->{PROPERTIES};	}	my $data = ParseType($d->{DATA}, $pointer_default);	$data->{ALIGN} = align_type($d->{NAME});	return {		NAME => $d->{NAME},		TYPE => $d->{TYPE},		PROPERTIES => $d->{PROPERTIES},		DATA => $data,		ORIGINAL => $d	};}sub ParseConst($$){	my ($ndr,$d) = @_;	return $d;}sub ParseFunction($$$){	my ($ndr,$d,$opnum) = @_;	my @elements = ();	my $rettype = undef;	my $thisopnum = undef;	CheckPointerTypes($d, $ndr->{PROPERTIES}->{pointer_default_top});	if (not defined($d->{PROPERTIES}{noopnum})) {		$thisopnum = ${$opnum};		${$opnum}++;	}	foreach my $x (@{$d->{ELEMENTS}}) {		my $e = ParseElement($x, $ndr->{PROPERTIES}->{pointer_default});		push (@{$e->{DIRECTION}}, "in") if (has_property($x, "in"));		push (@{$e->{DIRECTION}}, "out") if (has_property($x, "out"));		push (@elements, $e);

⌨️ 快捷键说明

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