1 ###################################################
2 # Samba4 NDR info tree generator
3 # Copyright tridge@samba.org 2000-2003
4 # Copyright tpot@samba.org 2001
5 # Copyright jelmer@samba.org 2004-2005
6 # released under the GNU GPL
13 #####################################################################
14 # return a table describing the order in which the parts of an element
16 # Possible level types:
22 sub GetElementLevelTable($)
26 return ($e->{NDR_ORDER_TABLE}) if (defined $e->{NDR_ORDER_TABLE});
31 # FIXME: Process {ARRAY_SIZE} kinds of arrays
33 # First, all the pointers
34 foreach my $i (1..need_wire_pointer($e)) {
37 # for now, there can only be one pointer type per element
38 POINTER_TYPE => pointer_type($e),
39 IS_DEFERRED => "$is_deferred"
41 # everything that follows will be deferred
43 # FIXME: Process array here possibly (in case of multi-dimensional arrays, etc)
46 if (defined($e->{ARRAY_LEN})) {
49 ARRAY_TYPE => array_type($e),
50 SIZE_IS => util::has_property($e, "size_is"),
51 LENGTH_IS => util::has_property($e, "length_is"),
52 IS_DEFERRED => "$is_deferred"
56 if (my $sub_size = util::has_property($e, "subcontext")) {
59 SUBCONTEXT_SIZE => $sub_size,
60 IS_DEFERRED => $is_deferred,
61 COMPRESSION => util::has_property($e, "compression")
65 if (my $switch = util::has_property($e, "switch_is")) {
69 IS_DEFERRED => $is_deferred
75 DATA_TYPE => $e->{TYPE},
77 IS_DEFERRED => $is_deferred,
78 CONTAINS_DEFERRED => can_contain_deferred($e)
81 $e->{NDR_ORDER_TABLE} = $order;
86 #####################################################################
87 # see if a type contains any deferred data
88 sub can_contain_deferred
92 return 1 if ($e->{POINTERS});
93 return 0 if (is_scalar_type($e->{TYPE}));
94 return 0 if (util::has_property($e, "subcontext"));
95 return 1 unless (typelist::hasType($e->{TYPE})); # assume the worst
97 my $type = typelist::getType($e->{TYPE});
99 foreach my $x (@{$type->{DATA}->{ELEMENTS}}) {
100 return 1 if (can_contain_deferred ($x));
106 sub is_scalar_type($)
110 return 0 unless typelist::hasType($type);
112 if (my $dt = typelist::getType($type)->{DATA}->{TYPE}) {
113 return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP");
123 return undef unless $e->{POINTERS};
125 return "ref" if (util::has_property($e, "ref"));
126 return "ptr" if (util::has_property($e, "ptr"));
127 return "unique" if (util::has_property($e, "unique"));
128 return "relative" if (util::has_property($e, "relative"));
129 return "ignore" if (util::has_property($e, "ignore"));
134 # return 1 if this is a fixed array
135 sub is_fixed_array($)
138 my $len = $e->{"ARRAY_LEN"};
139 return 1 if (defined $len && util::is_constant($len));
143 # return 1 if this is a conformant array
144 sub is_conformant_array($)
147 return 1 if (util::has_property($e, "size_is"));
151 # return 1 if this is a inline array
152 sub is_inline_array($)
155 my $len = $e->{"ARRAY_LEN"};
156 if (is_fixed_array($e) ||
157 defined $len && $len ne "*") {
163 # return 1 if this is a varying array
164 sub is_varying_array($)
167 return util::has_property($e, "length_is");
170 # return 1 if this is a surrounding array (sometimes
171 # referred to as an embedded array). Can only occur as
172 # the last element in a struct and can not contain any pointers.
173 sub is_surrounding_array($)
177 return ($e->{POINTERS} == 0
178 and defined $e->{ARRAY_LEN}
179 and $e->{ARRAY_LEN} eq "*"
180 and $e == $e->{PARENT}->{ELEMENTS}[-1]
181 and $e->{PARENT}->{TYPE} ne "FUNCTION");
188 return "conformant-varying" if (is_varying_array($e) and is_conformant_array($e));
189 return "conformant" if (is_varying_array($e));
190 return "varying" if (is_varying_array($e));
191 return "inline" if (is_inline_array($e));
192 return "fixed" if (is_fixed_array($e));
197 #####################################################################
198 # work out the correct alignment for a structure or union
199 sub find_largest_alignment($)
204 for my $e (@{$s->{ELEMENTS}}) {
207 if (Ndr::need_wire_pointer($e)) {
210 $a = align_type($e->{TYPE});
213 $align = $a if ($align < $a);
219 #####################################################################
225 unless (typelist::hasType($e)) {
226 # it must be an external type - all we can do is guess
227 # print "Warning: assuming alignment of unknown type '$e' is 4\n";
231 my $dt = typelist::getType($e)->{DATA};
233 if ($dt->{TYPE} eq "ENUM") {
234 return align_type(typelist::enum_type_fn($dt));
235 } elsif ($dt->{TYPE} eq "BITMAP") {
236 return align_type(typelist::bitmap_type_fn($dt));
237 } elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) {
238 return find_largest_alignment($dt);
239 } elsif ($dt->{TYPE} eq "SCALAR") {
240 return typelist::getScalarAlignment($dt->{NAME});
243 die("Unknown data type type $dt->{TYPE}");
246 # determine if an element needs a reference pointer on the wire
247 # in its NDR representation
248 sub need_wire_pointer($)
252 my $n = $e->{POINTERS};
253 my $pt = pointer_type($e);
255 # Top level "ref" pointers do not have a referrent identifier
258 and $e->{PARENT}->{TYPE} eq "FUNCTION")
272 PROPERTIES => $e->{PROPERTIES},
273 LEVELS => GetElementLevelTable($e)
282 foreach my $x (@{$e->{ELEMENTS}})
284 push @elements, ParseElement($x);
289 ELEMENTS => \@elements,
290 PROPERTIES => $e->{PROPERTIES}
299 foreach my $x (@{$e->{ELEMENTS}})
302 if ($x->{TYPE} eq "EMPTY") {
303 $t = { TYPE => "EMPTY" };
305 $t = ParseElement($x);
306 if (util::has_property($t, "default")) {
307 $t->{DEFAULT} = "default";
309 $t->{CASE} = $t->{PROPERTIES}->{CASE};
317 ELEMENTS => \@elements,
318 PROPERTIES => $e->{PROPERTIES}
328 ELEMENTS => $e->{ELEMENTS},
329 PROPERTIES => $e->{PROPERTIES}
339 ELEMENTS => $e->{ELEMENTS},
340 PROPERTIES => $e->{PROPERTIES}
350 if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") {
351 CheckPointerTypes($d->{DATA}, $ndr->{PROPERTIES}->{pointer_default});
354 if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) {
355 $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES};
358 if ($d->{DATA}->{TYPE} eq "STRUCT") {
359 $data = ParseStruct($d->{DATA});
360 } elsif ($d->{DATA}->{TYPE} eq "UNION") {
361 $data = ParseUnion($d->{DATA});
362 } elsif ($d->{DATA}->{TYPE} eq "ENUM") {
363 $data = ParseEnum($d->{DATA});
364 } elsif ($d->{DATA}->{TYPE} eq "BITMAP") {
365 $data = ParseBitmap($d->{DATA});
367 die("Unknown data type '$d->{DATA}->{TYPE}'");
370 $data->{ALIGN} = align_type($d->{NAME});
375 PROPERTIES => $d->{PROPERTIES},
380 sub ParseFunction($$)
387 CheckPointerTypes($d,
388 $ndr->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref"
391 foreach my $x (@{$d->{ELEMENTS}}) {
392 if (util::has_property($x, "in")) {
393 push (@in, ParseElement($x));
395 if (util::has_property($x, "out")) {
396 push (@out, ParseElement($x));
403 RETURN_TYPE => $d->{RETURN_TYPE},
404 PROPERTIES => $d->{PROPERTIES},
412 sub CheckPointerTypes($$)
417 foreach my $e (@{$s->{ELEMENTS}}) {
418 if ($e->{POINTERS}) {
419 if (not defined(Ndr::pointer_type($e))) {
420 $e->{PROPERTIES}->{$default} = 1;
423 if (Ndr::pointer_type($e) eq "ptr") {
424 print "Warning: ptr is not supported by pidl yet\n";
430 sub ParseInterface($)
437 if (not util::has_property($idl, "pointer_default")) {
438 # MIDL defaults to "ptr" in DCE compatible mode (/osf)
439 # and "unique" in Microsoft Extensions mode (default)
440 $idl->{PROPERTIES}->{pointer_default} = "unique";
443 foreach my $d (@{$idl->{DATA}}) {
444 if ($d->{TYPE} eq "DECLARE" or $d->{TYPE} eq "TYPEDEF") {
445 push (@typedefs, ParseTypedef($idl, $d));
448 if ($d->{TYPE} eq "FUNCTION") {
449 push (@functions, ParseFunction($idl, $d));
455 if(defined $idl->{PROPERTIES}->{version}) {
456 $version = $idl->{PROPERTIES}->{version};
461 NAME => $idl->{NAME},
462 UUID => util::has_property($idl, "uuid"),
465 PROPERTIES => $idl->{PROPERTIES},
466 FUNCTIONS => \@functions,
467 TYPEDEFS => \@typedefs
471 # Convert a IDL tree to a NDR tree
472 # Gives a result tree describing all that's necessary for easily generating
474 # - list of interfaces
475 # - list with functions
476 # - list with in elements
477 # - list with out elements
479 # - list with structs
480 # - alignment of structure
481 # - list with elements
483 # - alignment of union
484 # - list with elements
487 # - list with bitmaps
492 # properties are saved
493 # pointer types explicitly specified
499 foreach my $x (@{$idl}) {
500 push @ndr, ParseInterface($x);