1 ###################################################
2 # utility functions to support pidl
3 # Copyright tridge@samba.org 2000
4 # released under the GNU GPL
9 #####################################################################
10 # load a data structure from a file (as saved with SaveStructure)
14 my $contents = FileLoad
($f);
15 return eval "$contents";
20 #####################################################################
21 # flatten an array of arrays into a single array
34 #####################################################################
35 # flatten an array of arrays into a single array
48 #####################################################################
49 # flatten an array of hashes into a single hash
55 for my $k (keys %{$d}) {
63 #####################################################################
64 # traverse a perl data structure removing any empty arrays or
65 # hashes and any hash elements that map to undef
70 if (ref($v) eq "ARRAY") {
71 foreach my $i (0 .. $#{$v}) {
73 if (ref($v->[$i]) eq "ARRAY" && $#{$v->[$i]}==-1) { delete($v->[$i]); next; }
75 # this removes any undefined elements from the array
76 @
{$v} = grep { defined $_ } @
{$v};
77 } elsif (ref($v) eq "HASH") {
78 foreach my $x (keys %{$v}) {
80 if (!defined $v->{$x}) { delete($v->{$x}); next; }
81 if (ref($v->{$x}) eq "ARRAY" && $#{$v->{$x}}==-1) { delete($v->{$x}); next; }
87 #####################################################################
88 # return the modification time of a file
91 my($filename) = shift;
92 return (stat($filename))[9];
96 #####################################################################
97 # read a file into a string
100 my($filename) = shift;
102 open(INPUTFILE
, $filename) || return undef;
103 my($saved_delim) = $/;
105 my($data) = <INPUTFILE
>;
111 #####################################################################
112 # write a string into a file
115 my($filename) = shift;
118 open(FILE
, ">$filename") || die "can't open $filename";
123 #####################################################################
124 # return a filename with a changed extension
125 sub ChangeExtension
($$)
129 if ($fname =~ /^(.*)\.(.*?)$/) {
132 return "$fname.$ext";
135 #####################################################################
136 # save a data structure into a file
137 sub SaveStructure
($$)
139 my($filename) = shift;
141 FileSave
($filename, Dumper
($v));
144 #####################################################################
145 # see if a pidl property list contains a give property
151 if (!defined $e->{PROPERTIES
}) {
155 my($props) = $e->{PROPERTIES
};
157 foreach my $d (@
{$props}) {
158 if (ref($d) ne "HASH") {
163 foreach my $k (keys %{$d}) {
175 sub is_scalar_type
($)
179 return 1, if ($type eq "uint32");
180 return 1, if ($type eq "long");
181 return 1, if ($type eq "short");
182 return 1, if ($type eq "char");
183 return 1, if ($type eq "uint8");
184 return 1, if ($type eq "uint16");
185 return 1, if ($type eq "NTTIME");
186 return 1, if ($type eq "HYPER_T");
187 return 1, if ($type eq "wchar_t");
188 return 1, if ($type eq "DATA_BLOB");
193 # return the NDR alignment for a type
197 my $type = $e->{TYPE
};
199 if (need_wire_pointer
($e)) {
203 return 4, if ($type eq "uint32");
204 return 4, if ($type eq "long");
205 return 2, if ($type eq "short");
206 return 1, if ($type eq "char");
207 return 1, if ($type eq "uint8");
208 return 2, if ($type eq "uint16");
209 return 4, if ($type eq "NTTIME");
210 return 8, if ($type eq "HYPER_T");
211 return 2, if ($type eq "wchar_t");
212 return 4, if ($type eq "DATA_BLOB");
214 # it must be an external type - all we can do is guess
218 # this is used to determine if the ndr push/pull functions will need
219 # a ndr_flags field to split by buffers/scalars
220 sub is_builtin_type
($)
224 return 1, if (is_scalar_type
($type));
225 return 1, if ($type =~ "unistr.*");
226 return 1, if ($type eq "policy_handle");
231 # determine if an element needs a reference pointer on the wire
232 # in its NDR representation
233 sub need_wire_pointer
($)
236 if ($e->{POINTERS
} &&
237 !has_property
($e, "ref")) {
238 return $e->{POINTERS
};
243 # determine if an element is a pass-by-reference structure
247 if (!is_scalar_type
($e->{TYPE
}) &&
248 has_property
($e, "ref")) {
254 # determine if an element is a pure scalar. pure scalars do not
255 # have a "buffers" section in NDR
256 sub is_pure_scalar
($)
259 if (has_property
($e, "ref")) {
262 if (is_scalar_type
($e->{TYPE
}) &&
270 # determine the array size (size_is() or ARRAY_LEN)
274 my $size = has_property
($e, "size_is");
278 $size = $e->{ARRAY_LEN
};
285 # see if a variable needs to be allocated by the NDR subsystem on pull
290 if (has_property
($e, "ref")) {
294 if ($e->{POINTERS
} || array_size
($e)) {
301 # determine the C prefix used to refer to a variable when passing to a push
302 # function. This will be '*' for pointers to scalar types, '' for scalar
303 # types and normal pointers and '&' for pass-by-reference structures
307 if (is_scalar_type
($e->{TYPE
}) &&
311 if (!is_scalar_type
($e->{TYPE
}) &&
320 # determine the C prefix used to refer to a variable when passing to a pull
326 if (!$e->{POINTERS
} && !array_size
($e)) {
330 if ($e->{TYPE
} =~ "unistr.*" ||
331 $e->{TYPE
} =~ "nstring.*" ||
332 $e->{TYPE
} =~ "lstring.*") {
339 # determine if an element has a direct buffers component
340 sub has_direct_buffers
($)
343 if ($e->{POINTERS
} || array_size
($e)) {
349 # return 1 if the string is a C constant
359 # return 1 if this is a fixed array
360 sub is_fixed_array
($)
363 my $len = $e->{"ARRAY_LEN"};
364 if (defined $len && is_constant
($len)) {
370 # return 1 if this is a inline array
371 sub is_inline_array
($)
374 my $len = $e->{"ARRAY_LEN"};
375 if (is_fixed_array
($e) ||
376 defined $len && $len ne "*") {