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 if (!defined $e->{PROPERTIES}) {
157 my($props) = $e->{PROPERTIES};
159 foreach my $d (@{$props}) {
160 if (ref($d) ne "HASH") {
165 foreach my $k (keys %{$d}) {
177 sub is_scalar_type($)
181 return 1, if ($type eq "uint32");
182 return 1, if ($type eq "long");
183 return 1, if ($type eq "short");
184 return 1, if ($type eq "char");
185 return 1, if ($type eq "uint8");
186 return 1, if ($type eq "uint16");
187 return 1, if ($type eq "NTTIME");
188 return 1, if ($type eq "HYPER_T");
189 return 1, if ($type eq "wchar_t");
190 return 1, if ($type eq "DATA_BLOB");
195 # return the NDR alignment for a type
199 my $type = $e->{TYPE};
201 if (need_wire_pointer($e)) {
205 return 4, if ($type eq "uint32");
206 return 4, if ($type eq "long");
207 return 2, if ($type eq "short");
208 return 1, if ($type eq "char");
209 return 1, if ($type eq "uint8");
210 return 2, if ($type eq "uint16");
211 return 4, if ($type eq "NTTIME");
212 return 8, if ($type eq "HYPER_T");
213 return 2, if ($type eq "wchar_t");
214 return 4, if ($type eq "DATA_BLOB");
216 # it must be an external type - all we can do is guess
220 # this is used to determine if the ndr push/pull functions will need
221 # a ndr_flags field to split by buffers/scalars
222 sub is_builtin_type($)
226 return 1, if (is_scalar_type($type));
227 return 1, if ($type =~ "unistr.*");
228 return 1, if ($type eq "policy_handle");
233 # determine if an element needs a reference pointer on the wire
234 # in its NDR representation
235 sub need_wire_pointer($)
238 if ($e->{POINTERS} &&
239 !has_property($e, "ref")) {
240 return $e->{POINTERS};
246 # determine if an element is a pass-by-reference structure
250 if (!is_scalar_type($e->{TYPE}) &&
251 has_property($e, "ref")) {
257 # determine if an element is a pure scalar. pure scalars do not
258 # have a "buffers" section in NDR
259 sub is_pure_scalar($)
262 if (has_property($e, "ref")) {
265 if (is_scalar_type($e->{TYPE}) &&
273 # determine the array size (size_is() or ARRAY_LEN)
277 my $size = has_property($e, "size_is");
281 $size = $e->{ARRAY_LEN};
288 # see if a variable needs to be allocated by the NDR subsystem on pull
293 if (has_property($e, "ref")) {
297 if ($e->{POINTERS} || array_size($e)) {
304 # determine the C prefix used to refer to a variable when passing to a push
305 # function. This will be '*' for pointers to scalar types, '' for scalar
306 # types and normal pointers and '&' for pass-by-reference structures
310 if (is_scalar_type($e->{TYPE}) &&
314 if (!is_scalar_type($e->{TYPE}) &&
322 # determine the C prefix used to refer to a variable when passing to a pull
328 if (!$e->{POINTERS} && !array_size($e)) {
332 if ($e->{TYPE} =~ "unistr.*" ||
333 $e->{TYPE} =~ "nstring.*" ||
334 $e->{TYPE} =~ "lstring.*") {
341 # determine if an element has a direct buffers component
342 sub has_direct_buffers($)
345 if ($e->{POINTERS} || array_size($e)) {
351 # return 1 if the string is a C constant
361 # return 1 if this is a fixed array
362 sub is_fixed_array($)
365 my $len = $e->{"ARRAY_LEN"};
366 if (defined $len && is_constant($len)) {
372 # return 1 if this is a inline array
373 sub is_inline_array($)
376 my $len = $e->{"ARRAY_LEN"};
377 if (is_fixed_array($e) ||
378 defined $len && $len ne "*") {