use a precompiled grammer in pidl. This speeds up pidl by about a
[Samba/gebeck_regimport.git] / source / build / pidl / util.pm
blobc3f46dc8173775af7475b89d165de500253cc06f
1 ###################################################
2 # utility functions to support pidl
3 # Copyright tridge@samba.org 2000
4 # released under the GNU GPL
5 package util;
7 use Data::Dumper;
9 #####################################################################
10 # load a data structure from a file (as saved with SaveStructure)
11 sub LoadStructure($)
13 my $f = shift;
14 my $contents = FileLoad($f);
15 return eval "$contents";
18 use strict;
20 #####################################################################
21 # flatten an array of arrays into a single array
22 sub FlattenArray2($)
24 my $a = shift;
25 my @b;
26 for my $d (@{$a}) {
27 for my $d1 (@{$d}) {
28 push(@b, $d1);
31 return \@b;
34 #####################################################################
35 # flatten an array of arrays into a single array
36 sub FlattenArray($)
38 my $a = shift;
39 my @b;
40 for my $d (@{$a}) {
41 for my $d1 (@{$d}) {
42 push(@b, $d1);
45 return \@b;
48 #####################################################################
49 # flatten an array of hashes into a single hash
50 sub FlattenHash($)
52 my $a = shift;
53 my %b;
54 for my $d (@{$a}) {
55 for my $k (keys %{$d}) {
56 $b{$k} = $d->{$k};
59 return \%b;
63 #####################################################################
64 # traverse a perl data structure removing any empty arrays or
65 # hashes and any hash elements that map to undef
66 sub CleanData($)
68 sub CleanData($);
69 my($v) = shift;
70 if (ref($v) eq "ARRAY") {
71 foreach my $i (0 .. $#{$v}) {
72 CleanData($v->[$i]);
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}) {
79 CleanData($v->{$x});
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
89 sub FileModtime($)
91 my($filename) = shift;
92 return (stat($filename))[9];
96 #####################################################################
97 # read a file into a string
98 sub FileLoad($)
100 my($filename) = shift;
101 local(*INPUTFILE);
102 open(INPUTFILE, $filename) || return undef;
103 my($saved_delim) = $/;
104 undef $/;
105 my($data) = <INPUTFILE>;
106 close(INPUTFILE);
107 $/ = $saved_delim;
108 return $data;
111 #####################################################################
112 # write a string into a file
113 sub FileSave($$)
115 my($filename) = shift;
116 my($v) = shift;
117 local(*FILE);
118 open(FILE, ">$filename") || die "can't open $filename";
119 print FILE $v;
120 close(FILE);
123 #####################################################################
124 # return a filename with a changed extension
125 sub ChangeExtension($$)
127 my($fname) = shift;
128 my($ext) = shift;
129 if ($fname =~ /^(.*)\.(.*?)$/) {
130 return "$1.$ext";
132 return "$fname.$ext";
135 #####################################################################
136 # save a data structure into a file
137 sub SaveStructure($$)
139 my($filename) = shift;
140 my($v) = shift;
141 FileSave($filename, Dumper($v));
144 #####################################################################
145 # see if a pidl property list contains a give property
146 sub has_property($$)
148 my($e) = shift;
149 my($p) = shift;
151 if (!defined $e->{PROPERTIES}) {
152 return;
155 my($props) = $e->{PROPERTIES};
157 foreach my $d (@{$props}) {
158 if (ref($d) ne "HASH") {
159 if ($d eq $p) {
160 return 1;
162 } else {
163 foreach my $k (keys %{$d}) {
164 if ($k eq $p) {
165 return $d->{$k};
171 return undef;
175 sub is_scalar_type($)
177 my($type) = shift;
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");
190 return 0;
193 # return the NDR alignment for a type
194 sub type_align($)
196 my($e) = shift;
197 my $type = $e->{TYPE};
199 if (need_wire_pointer($e)) {
200 return 4;
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
215 return 4;
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($)
222 my($type) = shift;
224 return 1, if (is_scalar_type($type));
225 return 1, if ($type =~ "unistr.*");
226 return 1, if ($type eq "policy_handle");
228 return 0;
231 # determine if an element needs a reference pointer on the wire
232 # in its NDR representation
233 sub need_wire_pointer($)
235 my $e = shift;
236 if ($e->{POINTERS} &&
237 !has_property($e, "ref")) {
238 return $e->{POINTERS};
240 return undef;
243 # determine if an element is a pass-by-reference structure
244 sub is_ref_struct($)
246 my $e = shift;
247 if (!is_scalar_type($e->{TYPE}) &&
248 has_property($e, "ref")) {
249 return 1;
251 return 0;
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($)
258 my $e = shift;
259 if (has_property($e, "ref")) {
260 return 1;
262 if (is_scalar_type($e->{TYPE}) &&
263 !$e->{POINTERS} &&
264 !array_size($e)) {
265 return 1;
267 return 0;
270 # determine the array size (size_is() or ARRAY_LEN)
271 sub array_size($)
273 my $e = shift;
274 my $size = has_property($e, "size_is");
275 if ($size) {
276 return $size;
278 $size = $e->{ARRAY_LEN};
279 if ($size) {
280 return $size;
282 return undef;
285 # see if a variable needs to be allocated by the NDR subsystem on pull
286 sub need_alloc($)
288 my $e = shift;
290 if (has_property($e, "ref")) {
291 return 0;
294 if ($e->{POINTERS} || array_size($e)) {
295 return 1;
298 return 0;
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
304 sub c_push_prefix($)
306 my $e = shift;
307 if (is_scalar_type($e->{TYPE}) &&
308 $e->{POINTERS}) {
309 return "*";
311 if (!is_scalar_type($e->{TYPE}) &&
312 !$e->{POINTERS} &&
313 !array_size($e)) {
314 return "&";
316 return "";
320 # determine the C prefix used to refer to a variable when passing to a pull
321 # return '&' or ''
322 sub c_pull_prefix($)
324 my $e = shift;
326 if (!$e->{POINTERS} && !array_size($e)) {
327 return "&";
330 if ($e->{TYPE} =~ "unistr.*" ||
331 $e->{TYPE} =~ "nstring.*" ||
332 $e->{TYPE} =~ "lstring.*") {
333 return "&";
336 return "";
339 # determine if an element has a direct buffers component
340 sub has_direct_buffers($)
342 my $e = shift;
343 if ($e->{POINTERS} || array_size($e)) {
344 return 1;
346 return 0;
349 # return 1 if the string is a C constant
350 sub is_constant($)
352 my $s = shift;
353 if ($s =~ /^\d/) {
354 return 1;
356 return 0;
359 # return 1 if this is a fixed array
360 sub is_fixed_array($)
362 my $e = shift;
363 my $len = $e->{"ARRAY_LEN"};
364 if (defined $len && is_constant($len)) {
365 return 1;
367 return 0;
370 # return 1 if this is a inline array
371 sub is_inline_array($)
373 my $e = shift;
374 my $len = $e->{"ARRAY_LEN"};
375 if (is_fixed_array($e) ||
376 defined $len && $len ne "*") {
377 return 1;
379 return 0;
382 sub dump($)
384 print Dumper shift;