1 ###################################################
2 # utility functions to support pidl
3 # Copyright tridge@samba.org 2000
4 # released under the GNU GPL
15 #####################################################################
16 # flatten an array of arrays into a single array
29 #####################################################################
30 # flatten an array of arrays into a single array
43 #####################################################################
44 # flatten an array of hashes into a single hash
50 for my $k (keys %{$d}) {
58 #####################################################################
59 # traverse a perl data structure removing any empty arrays or
60 # hashes and any hash elements that map to undef
65 if (ref($v) eq "ARRAY") {
66 foreach my $i (0 .. $#{$v}) {
68 if (ref($v->[$i]) eq "ARRAY" && $#{$v->[$i]}==-1) { delete($v->[$i]); next; }
70 # this removes any undefined elements from the array
71 @{$v} = grep { defined $_ } @{$v};
72 } elsif (ref($v) eq "HASH") {
73 foreach my $x (keys %{$v}) {
75 if (!defined $v->{$x}) { delete($v->{$x}); next; }
76 if (ref($v->{$x}) eq "ARRAY" && $#{$v->{$x}}==-1) { delete($v->{$x}); next; }
82 #####################################################################
83 # return the modification time of a file
86 my($filename) = shift;
87 return (stat($filename))[9];
91 #####################################################################
92 # read a file into a string
95 my($filename) = shift;
97 open(INPUTFILE, $filename) || die "can't load $filename";
98 my($saved_delim) = $/;
100 my($data) = <INPUTFILE>;
106 #####################################################################
107 # write a string into a file
110 my($filename) = shift;
113 open(FILE, ">$filename") || die "can't open $filename";
118 #####################################################################
119 # return a filename with a changed extension
120 sub ChangeExtension($$)
124 if ($fname =~ /^(.*)\.(.*?)$/) {
127 return "$fname.$ext";
130 #####################################################################
131 # save a data structure into a file
132 sub SaveStructure($$)
134 my($filename) = shift;
136 FileSave($filename, Dumper($v));
139 #####################################################################
140 # load a data structure from a file (as saved with SaveStructure)
143 return eval FileLoad(shift);
146 #####################################################################
147 # see if a pidl property list contains a give property
153 my($props) = $e->{PROPERTIES};
155 foreach my $d (@{$props}) {
156 if (ref($d) ne "HASH") {
161 foreach my $k (keys %{$d}) {
173 sub is_scalar_type($)
177 return 1, if ($type eq "uint32");
178 return 1, if ($type eq "long");
179 return 1, if ($type eq "short");
180 return 1, if ($type eq "char");
181 return 1, if ($type eq "uint8");
182 return 1, if ($type eq "uint16");
183 return 1, if ($type eq "NTTIME");
184 return 1, if ($type eq "hyper");
185 return 1, if ($type eq "wchar_t");
190 # return the NDR alignment for a type
194 my $type = $e->{TYPE};
196 if ($e->{POINTERS} || array_size($e)) {
197 # FIXME: we really should recurse here
201 return 4, if ($type eq "uint32");
202 return 4, if ($type eq "long");
203 return 2, if ($type eq "short");
204 return 1, if ($type eq "char");
205 return 1, if ($type eq "uint8");
206 return 2, if ($type eq "uint16");
207 return 4, if ($type eq "NTTIME");
208 return 8, if ($type eq "hyper");
209 return 2, if ($type eq "wchar_t");
214 # this is used to determine if the ndr push/pull functions will need
215 # a ndr_flags field to split by buffers/scalars
216 sub is_builtin_type($)
220 return 1, if (is_scalar_type($type));
221 return 1, if ($type =~ "unistr.*");
222 return 1, if ($type eq "security_descriptor");
223 return 1, if ($type eq "dom_sid");
224 return 1, if ($type eq "dom_sid2");
225 return 1, if ($type eq "policy_handle");
230 # determine if an element needs a reference pointer on the wire
231 # in its NDR representation
232 sub need_wire_pointer($)
235 if ($e->{POINTERS} &&
236 !has_property($e, "ref")) {
237 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}) &&
319 # determine the C prefix used to refer to a variable when passing to a pull
325 if (!$e->{POINTERS} && !array_size($e)) {
329 if ($e->{TYPE} =~ "unistr.*") {
336 # determine if an element has a direct buffers component
337 sub has_direct_buffers($)
340 if ($e->{POINTERS} || array_size($e)) {