1 ###################################################
2 # utility functions to support pidl
3 # Copyright tridge@samba.org 2000
4 # released under the GNU GPL
7 #####################################################################
8 # load a data structure from a file (as saved with SaveStructure)
12 my $contents = FileLoad($f);
13 defined $contents || return undef;
14 return eval "$contents";
19 #####################################################################
20 # flatten an array of arrays into a single array
33 #####################################################################
34 # flatten an array of arrays into a single array
47 #####################################################################
48 # flatten an array of hashes into a single hash
54 for my $k (keys %{$d}) {
62 #####################################################################
63 # traverse a perl data structure removing any empty arrays or
64 # hashes and any hash elements that map to undef
69 if (ref($v) eq "ARRAY") {
70 foreach my $i (0 .. $#{$v}) {
72 if (ref($v->[$i]) eq "ARRAY" && $#{$v->[$i]}==-1) {
77 # this removes any undefined elements from the array
78 @{$v} = grep { defined $_ } @{$v};
79 } elsif (ref($v) eq "HASH") {
80 foreach my $x (keys %{$v}) {
82 if (!defined $v->{$x}) { delete($v->{$x}); next; }
83 if (ref($v->{$x}) eq "ARRAY" && $#{$v->{$x}}==-1) { delete($v->{$x}); next; }
89 #####################################################################
90 # return the modification time of a file
93 my($filename) = shift;
94 return (stat($filename))[9];
98 #####################################################################
99 # read a file into a string
102 my($filename) = shift;
104 open(INPUTFILE, $filename) || return undef;
105 my($saved_delim) = $/;
107 my($data) = <INPUTFILE>;
113 #####################################################################
114 # write a string into a file
117 my($filename) = shift;
120 open(FILE, ">$filename") || die "can't open $filename";
125 #####################################################################
126 # return a filename with a changed extension
127 sub ChangeExtension($$)
131 if ($fname =~ /^(.*)\.(.*?)$/) {
137 #####################################################################
138 # a dumper wrapper to prevent dependence on the Data::Dumper module
139 # unless we actually need it
142 require Data::Dumper;
144 return Data::Dumper::Dumper($s);
147 #####################################################################
148 # save a data structure into a file
149 sub SaveStructure($$)
151 my($filename) = shift;
153 FileSave($filename, MyDumper($v));
156 #####################################################################
157 # find an interface in an array of interfaces
158 sub get_interface($$)
164 if($_->{NAME} eq $n) { return $_; }
170 #####################################################################
171 # see if a pidl property list contains a give property
177 if (!defined $e->{PROPERTIES}) {
181 return $e->{PROPERTIES}->{$p};
185 sub is_scalar_type($)
189 if ($type =~ /^u?int\d+/) {
192 if ($type =~ /char|short|long|NTTIME|
193 time_t|error_status_t|boolean32|unsigned32|
194 HYPER_T|wchar_t|DATA_BLOB/x) {
201 # return the NDR alignment for a type
205 my $type = $e->{TYPE};
207 if (need_wire_pointer($e)) {
211 return 4, if ($type eq "uint32");
212 return 4, if ($type eq "long");
213 return 2, if ($type eq "short");
214 return 1, if ($type eq "char");
215 return 1, if ($type eq "uint8");
216 return 2, if ($type eq "uint16");
217 return 4, if ($type eq "NTTIME");
218 return 4, if ($type eq "time_t");
219 return 8, if ($type eq "HYPER_T");
220 return 2, if ($type eq "wchar_t");
221 return 4, if ($type eq "DATA_BLOB");
223 # it must be an external type - all we can do is guess
227 # this is used to determine if the ndr push/pull functions will need
228 # a ndr_flags field to split by buffers/scalars
229 sub is_builtin_type($)
233 return 1, if (is_scalar_type($type));
238 # determine if an element needs a reference pointer on the wire
239 # in its NDR representation
240 sub need_wire_pointer($)
243 if ($e->{POINTERS} &&
244 !has_property($e, "ref")) {
245 return $e->{POINTERS};
250 # determine if an element is a pass-by-reference structure
254 if (!is_scalar_type($e->{TYPE}) &&
255 has_property($e, "ref")) {
261 # determine if an element is a pure scalar. pure scalars do not
262 # have a "buffers" section in NDR
263 sub is_pure_scalar($)
266 if (has_property($e, "ref")) {
269 if (is_scalar_type($e->{TYPE}) &&
277 # determine the array size (size_is() or ARRAY_LEN)
281 my $size = has_property($e, "size_is");
285 $size = $e->{ARRAY_LEN};
292 # see if a variable needs to be allocated by the NDR subsystem on pull
297 if (has_property($e, "ref")) {
301 if ($e->{POINTERS} || array_size($e)) {
308 # determine the C prefix used to refer to a variable when passing to a push
309 # function. This will be '*' for pointers to scalar types, '' for scalar
310 # types and normal pointers and '&' for pass-by-reference structures
315 if ($e->{TYPE} =~ "string") {
319 if (is_scalar_type($e->{TYPE}) &&
323 if (!is_scalar_type($e->{TYPE}) &&
332 # determine the C prefix used to refer to a variable when passing to a pull
338 if (!$e->{POINTERS} && !array_size($e)) {
342 if ($e->{TYPE} =~ "string") {
349 # determine if an element has a direct buffers component
350 sub has_direct_buffers($)
353 if ($e->{POINTERS} || array_size($e)) {
359 # return 1 if the string is a C constant
363 if (defined $s && $s =~ /^\d/) {
369 # return 1 if this is a fixed array
370 sub is_fixed_array($)
373 my $len = $e->{"ARRAY_LEN"};
374 if (defined $len && is_constant($len)) {
380 # return 1 if this is a inline array
381 sub is_inline_array($)
384 my $len = $e->{"ARRAY_LEN"};
385 if (is_fixed_array($e) ||
386 defined $len && $len ne "*") {