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 return eval "$contents";
18 #####################################################################
19 # flatten an array of arrays into a single array
32 #####################################################################
33 # flatten an array of arrays into a single array
46 #####################################################################
47 # flatten an array of hashes into a single hash
53 for my $k (keys %{$d}) {
61 #####################################################################
62 # traverse a perl data structure removing any empty arrays or
63 # hashes and any hash elements that map to undef
68 if (ref($v) eq "ARRAY") {
69 foreach my $i (0 .. $#{$v}) {
71 if (ref($v->[$i]) eq "ARRAY" && $#{$v->[$i]}==-1) {
76 # this removes any undefined elements from the array
77 @{$v} = grep { defined $_ } @{$v};
78 } elsif (ref($v) eq "HASH") {
79 foreach my $x (keys %{$v}) {
81 if (!defined $v->{$x}) { delete($v->{$x}); next; }
82 if (ref($v->{$x}) eq "ARRAY" && $#{$v->{$x}}==-1) { delete($v->{$x}); next; }
88 #####################################################################
89 # return the modification time of a file
92 my($filename) = shift;
93 return (stat($filename))[9];
97 #####################################################################
98 # read a file into a string
101 my($filename) = shift;
103 open(INPUTFILE, $filename) || return undef;
104 my($saved_delim) = $/;
106 my($data) = <INPUTFILE>;
112 #####################################################################
113 # write a string into a file
116 my($filename) = shift;
119 open(FILE, ">$filename") || die "can't open $filename";
124 #####################################################################
125 # return a filename with a changed extension
126 sub ChangeExtension($$)
130 if ($fname =~ /^(.*)\.(.*?)$/) {
136 #####################################################################
137 # a dumper wrapper to prevent dependence on the Data::Dumper module
138 # unless we actually need it
141 require Data::Dumper;
143 return Data::Dumper::Dumper($s);
146 #####################################################################
147 # save a data structure into a file
148 sub SaveStructure($$)
150 my($filename) = shift;
152 FileSave($filename, MyDumper($v));
155 #####################################################################
156 # see if a pidl property list contains a give property
162 if (!defined $e->{PROPERTIES}) {
166 return $e->{PROPERTIES}->{$p};
170 sub is_scalar_type($)
174 if ($type =~ /uint\d+/) {
177 if ($type =~ /char|short|long|NTTIME|
178 time_t|error_status_t|boolean32|unsigned32|
179 HYPER_T|wchar_t|DATA_BLOB/x) {
186 # return the NDR alignment for a type
190 my $type = $e->{TYPE};
192 if (need_wire_pointer($e)) {
196 return 4, if ($type eq "uint32");
197 return 4, if ($type eq "long");
198 return 2, if ($type eq "short");
199 return 1, if ($type eq "char");
200 return 1, if ($type eq "uint8");
201 return 2, if ($type eq "uint16");
202 return 4, if ($type eq "NTTIME");
203 return 4, if ($type eq "time_t");
204 return 8, if ($type eq "HYPER_T");
205 return 2, if ($type eq "wchar_t");
206 return 4, if ($type eq "DATA_BLOB");
208 # it must be an external type - all we can do is guess
212 # this is used to determine if the ndr push/pull functions will need
213 # a ndr_flags field to split by buffers/scalars
214 sub is_builtin_type($)
218 return 1, if (is_scalar_type($type));
223 # determine if an element needs a reference pointer on the wire
224 # in its NDR representation
225 sub need_wire_pointer($)
228 if ($e->{POINTERS} &&
229 !has_property($e, "ref")) {
230 return $e->{POINTERS};
235 # determine if an element is a pass-by-reference structure
239 if (!is_scalar_type($e->{TYPE}) &&
240 has_property($e, "ref")) {
246 # determine if an element is a pure scalar. pure scalars do not
247 # have a "buffers" section in NDR
248 sub is_pure_scalar($)
251 if (has_property($e, "ref")) {
254 if (is_scalar_type($e->{TYPE}) &&
262 # determine the array size (size_is() or ARRAY_LEN)
266 my $size = has_property($e, "size_is");
270 $size = $e->{ARRAY_LEN};
277 # see if a variable needs to be allocated by the NDR subsystem on pull
282 if (has_property($e, "ref")) {
286 if ($e->{POINTERS} || array_size($e)) {
293 # determine the C prefix used to refer to a variable when passing to a push
294 # function. This will be '*' for pointers to scalar types, '' for scalar
295 # types and normal pointers and '&' for pass-by-reference structures
300 if ($e->{TYPE} =~ "string") {
304 if (is_scalar_type($e->{TYPE}) &&
308 if (!is_scalar_type($e->{TYPE}) &&
317 # determine the C prefix used to refer to a variable when passing to a pull
323 if (!$e->{POINTERS} && !array_size($e)) {
327 if ($e->{TYPE} =~ "string") {
334 # determine if an element has a direct buffers component
335 sub has_direct_buffers($)
338 if ($e->{POINTERS} || array_size($e)) {
344 # return 1 if the string is a C constant
354 # return 1 if this is a fixed array
355 sub is_fixed_array($)
358 my $len = $e->{"ARRAY_LEN"};
359 if (defined $len && is_constant($len)) {
365 # return 1 if this is a inline array
366 sub is_inline_array($)
369 my $len = $e->{"ARRAY_LEN"};
370 if (is_fixed_array($e) ||
371 defined $len && $len ne "*") {