r4540: sync enum and bitmap code
[samba.git] / source4 / build / pidl / parser.pm
1 ###################################################
2 # Samba4 parser generator for IDL structures
3 # Copyright tridge@samba.org 2000-2003
4 # Copyright tpot@samba.org 2001
5 # Copyright jelmer@samba.org 2004
6 # released under the GNU GPL
7
8 package IdlParser;
9
10 use strict;
11 use needed;
12
13 # the list of needed functions
14 my %structs;
15
16 sub pidl($)
17 {
18         print OUT shift;
19 }
20
21 #####################################################################
22 # parse a properties list
23 sub ParseProperties($)
24 {
25     my($props) = shift;
26     foreach my $d (@{$props}) {
27         if (ref($d) ne "HASH") {
28             pidl "[$d] ";
29         } else {
30             foreach my $k (keys %{$d}) {
31                 pidl "[$k($d->{$k})] ";
32             }
33         }
34     }
35 }
36
37 ###################################
38 # find a sibling var in a structure
39 sub find_sibling($$)
40 {
41         my($e) = shift;
42         my($name) = shift;
43         my($fn) = $e->{PARENT};
44
45         if ($name =~ /\*(.*)/) {
46                 $name = $1;
47         }
48
49         if ($fn->{TYPE} eq "FUNCTION") {
50                 for my $e2 (@{$fn->{DATA}}) {
51                         if ($e2->{NAME} eq $name) {
52                                 return $e2;
53                         }
54                 }
55         }
56
57         for my $e2 (@{$fn->{ELEMENTS}}) {
58                 if ($e2->{NAME} eq $name) {
59                         return $e2;
60                 }
61         }
62         die "invalid sibling '$name'";
63 }
64
65 ####################################################################
66 # work out the name of a size_is() variable
67 sub find_size_var($$$)
68 {
69         my($e) = shift;
70         my($size) = shift;
71         my($var_prefix) = shift;
72
73         my($fn) = $e->{PARENT};
74
75         if (util::is_constant($size)) {
76                 return $size;
77         }
78
79         if ($size =~ /ndr->|\(/) {
80                 return $size;
81         }
82
83         my $prefix = "";
84
85         if ($size =~ /\*(.*)/) {
86                 $size = $1;
87                 $prefix = "*";
88         }
89
90         if ($fn->{TYPE} ne "FUNCTION") {
91                 return $prefix . "r->$size";
92         }
93
94         my $e2 = find_sibling($e, $size);
95
96         if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
97                 return $prefix . "$var_prefix$size";
98         }
99         if (util::has_property($e2, "in")) {
100                 return $prefix . "r->in.$size";
101         }
102         if (util::has_property($e2, "out")) {
103                 return $prefix . "r->out.$size";
104         }
105
106         die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
107 }
108
109 #####################################################################
110 # check that a variable we get from find_size_var isn't a null pointer
111 sub check_null_pointer($)
112 {
113         my $size = shift;
114         if ($size =~ /^\*/) {
115                 my $size2 = substr($size, 1);
116                 pidl "\tif ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;\n";
117         }
118 }
119
120 #####################################################################
121 # check that a variable we get from find_size_var isn't a null pointer
122 # void return varient
123 sub check_null_pointer_void($)
124 {
125         my $size = shift;
126         if ($size =~ /^\*/) {
127                 my $size2 = substr($size, 1);
128                 pidl "\tif ($size2 == NULL) return;\n";
129         }
130 }
131
132
133 #####################################################################
134 # work out is a parse function should be declared static or not
135 sub fn_prefix($)
136 {
137         my $fn = shift;
138         if ($fn->{TYPE} eq "TYPEDEF") {
139                 if (util::has_property($fn, "public")) {
140                         return "";
141                 }
142         }
143
144         if ($fn->{TYPE} eq "FUNCTION") {
145                 if (util::has_property($fn, "public")) {
146                         return "";
147                 }
148         }
149         return "static ";
150 }
151
152
153 ###################################################################
154 # setup any special flags for an element or structure
155 sub start_flags($)
156 {
157         my $e = shift;
158         my $flags = util::has_property($e, "flag");
159         if (defined $flags) {
160                 pidl "\t{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;\n";
161                 pidl "\tndr_set_flags(&ndr->flags, $flags);\n";
162         }
163 }
164
165 ###################################################################
166 # end any special flags for an element or structure
167 sub end_flags($)
168 {
169         my $e = shift;
170         my $flags = util::has_property($e, "flag");
171         if (defined $flags) {
172                 pidl "\tndr->flags = _flags_save_$e->{TYPE};\n\t}\n";
173         }
174 }
175
176
177 #####################################################################
178 # work out the correct alignment for a structure
179 sub struct_alignment
180 {
181         my $s = shift;
182
183         my $align = 1;
184         for my $e (@{$s->{ELEMENTS}}) {
185                 my $a = 1;
186
187                 if (!util::need_wire_pointer($e)
188                     && defined $structs{$e->{TYPE}}) {
189                         if ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "STRUCT") {
190                                 $a = struct_alignment($structs{$e->{TYPE}}->{DATA});
191                         } elsif ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "UNION") {
192                                 if (defined $structs{$e->{TYPE}}->{DATA}) {
193                                         $a = union_alignment($structs{$e->{TYPE}}->{DATA});
194                                 }
195                         }
196                 } else {
197                         $a = util::type_align($e);
198                 }
199
200                 if ($align < $a) {
201                         $align = $a;
202                 }
203         }
204
205         return $align;
206 }
207
208 #####################################################################
209 # work out the correct alignment for a union
210 sub union_alignment
211 {
212         my $u = shift;
213
214         my $align = 1;
215
216         foreach my $e (@{$u->{DATA}}) {
217                 my $a = 1;
218
219                 if ($e->{TYPE} eq "EMPTY") {
220                         next;
221                 }
222
223                 if (!util::need_wire_pointer($e)
224                     && defined $structs{$e->{DATA}->{TYPE}}) {
225                         my $s = $structs{$e->{DATA}->{TYPE}};
226                         if ($s->{DATA}->{TYPE} eq "STRUCT") {
227                                 $a = struct_alignment($s->{DATA});
228                         } elsif ($s->{DATA}->{TYPE} eq "UNION") {
229                                 $a = union_alignment($s->{DATA});
230                         }
231                 } else {
232                         $a = util::type_align($e->{DATA});
233                 }
234
235                 if ($align < $a) {
236                         $align = $a;
237                 }
238         }
239
240         return $align;
241 }
242
243 #####################################################################
244 # parse an array - push side
245 sub ParseArrayPush($$$)
246 {
247         my $e = shift;
248         my $var_prefix = shift;
249         my $ndr_flags = shift;
250
251         my $size = find_size_var($e, util::array_size($e), $var_prefix);
252
253         if (defined $e->{CONFORMANT_SIZE}) {
254                 # the conformant size has already been pushed
255         } elsif (!util::is_inline_array($e)) {
256                 # we need to emit the array size
257                 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
258         }
259
260         if (my $length = util::has_property($e, "length_is")) {
261                 $length = find_size_var($e, $length, $var_prefix);
262                 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, 0));\n";
263                 pidl "\t\tNDR_CHECK(ndr_push_uint32(ndr, $length));\n";
264                 $size = $length;
265         }
266
267         if (util::is_scalar_type($e->{TYPE})) {
268                 pidl "\t\tNDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
269         } else {
270                 pidl "\t\tNDR_CHECK(ndr_push_array(ndr, $ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));\n";
271         }
272 }
273
274 #####################################################################
275 # print an array
276 sub ParseArrayPrint($$)
277 {
278         my $e = shift;
279         my $var_prefix = shift;
280         my $size = find_size_var($e, util::array_size($e), $var_prefix);
281         my $length = util::has_property($e, "length_is");
282
283         if (defined $length) {
284                 $size = find_size_var($e, $length, $var_prefix);
285         }
286
287         if (util::is_scalar_type($e->{TYPE})) {
288                 pidl "\t\tndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, $size);\n";
289         } else {
290                 pidl "\t\tndr_print_array(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});\n";
291         }
292 }
293
294 #####################################################################
295 # check the size_is and length_is constraints
296 sub CheckArraySizes($$)
297 {
298         my $e = shift;
299         my $var_prefix = shift;
300
301         if (!defined $e->{CONFORMANT_SIZE} && 
302             util::has_property($e, "size_is")) {
303                 my $size = find_size_var($e, util::array_size($e), $var_prefix);
304                 pidl "\tif ($var_prefix$e->{NAME}) {\n";
305                 check_null_pointer($size);
306                 pidl "\t\tNDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));\n";
307                 pidl "\t}\n";
308         }
309
310         if (my $length = util::has_property($e, "length_is")) {
311                 $length = find_size_var($e, $length, $var_prefix);
312                 pidl "\tif ($var_prefix$e->{NAME}) {\n";
313                 check_null_pointer($length);
314                 pidl "\t\tNDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));\n";
315                 pidl "\t}\n";
316         }
317 }
318
319
320 #####################################################################
321 # parse an array - pull side
322 sub ParseArrayPull($$$)
323 {
324         my $e = shift;
325         my $var_prefix = shift;
326         my $ndr_flags = shift;
327
328         my $size = find_size_var($e, util::array_size($e), $var_prefix);
329         my $alloc_size = $size;
330
331         # if this is a conformant array then we use that size to allocate, and make sure
332         # we allocate enough to pull the elements
333         if (defined $e->{CONFORMANT_SIZE}) {
334                 $alloc_size = $e->{CONFORMANT_SIZE};
335                 check_null_pointer($size);
336                 pidl "\tif ($size > $alloc_size) {\n";
337                 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n";
338                 pidl "\t}\n";
339         } elsif (!util::is_inline_array($e)) {
340                 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
341                         my $size2 = substr($size, 1);
342                         pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }\n";
343                 }
344
345                 # non fixed arrays encode the size just before the array
346                 pidl "\t\tNDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));\n";
347                 $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
348         }
349
350         if ((util::need_alloc($e) && !util::is_fixed_array($e)) ||
351             ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
352                 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
353                         pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);\n";
354                 }
355         }
356
357         if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
358                 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
359                         pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
360                         pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);\n";
361                         pidl "\t}\n";
362                 }
363         }
364
365         if (my $length = util::has_property($e, "length_is")) {
366                 pidl "\t\tNDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));\n";
367                 $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
368         }
369
370         check_null_pointer($size);
371         if (util::is_scalar_type($e->{TYPE})) {
372                 pidl "\t\tNDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));\n";
373         } else {
374                 pidl "\t\tNDR_CHECK(ndr_pull_array(ndr, $ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));\n";
375         }
376 }
377
378
379 #####################################################################
380 # parse scalars in a structure element
381 sub ParseElementPushScalar($$$)
382 {
383         my($e) = shift;
384         my($var_prefix) = shift;
385         my($ndr_flags) = shift;
386         my $cprefix = util::c_push_prefix($e);
387         my $sub_size = util::has_property($e, "subcontext");
388
389         start_flags($e);
390
391         if (my $value = util::has_property($e, "value")) {
392                 pidl "\t$cprefix$var_prefix$e->{NAME} = $value;\n";
393         }
394
395         if (util::has_property($e, "relative")) {
396                 pidl "\tNDR_CHECK(ndr_push_relative1(ndr, $var_prefix$e->{NAME}));\n";
397         } elsif (util::is_inline_array($e)) {
398                 ParseArrayPush($e, "r->", "NDR_SCALARS");
399         } elsif (util::need_wire_pointer($e)) {
400                 pidl "\tNDR_CHECK(ndr_push_ptr(ndr, $var_prefix$e->{NAME}));\n";
401         } elsif (util::need_alloc($e)) {
402                 # no scalar component
403         } elsif (my $switch = util::has_property($e, "switch_is")) {
404                 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
405         } elsif (defined $sub_size) {
406                 if (util::is_builtin_type($e->{TYPE})) {
407                         pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n";
408                 } else {
409                         pidl "\tNDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));\n";
410                 }
411         } elsif (util::is_builtin_type($e->{TYPE})) {
412                 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
413         } else {
414                 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
415         }
416
417         end_flags($e);
418 }
419
420 #####################################################################
421 # print scalars in a structure element
422 sub ParseElementPrintScalar($$)
423 {
424         my($e) = shift;
425         my($var_prefix) = shift;
426         my $cprefix = util::c_push_prefix($e);
427
428         if (util::has_property($e, "noprint")) {
429                 return;
430         }
431
432         if (my $value = util::has_property($e, "value")) {
433                 pidl "\tif (ndr->flags & LIBNDR_PRINT_SET_VALUES) {\n";
434                 pidl "\t\t$cprefix$var_prefix$e->{NAME} = $value;\n";
435                 pidl "\t}\n";
436         }
437
438         if (util::is_fixed_array($e)) {
439                 ParseElementPrintBuffer($e, $var_prefix);
440         } elsif (util::has_direct_buffers($e)) {
441                 pidl "\tndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});\n";
442                 pidl "\tndr->depth++;\n";
443                 ParseElementPrintBuffer($e, $var_prefix);
444                 pidl "\tndr->depth--;\n";
445         } elsif (my $switch = util::has_property($e, "switch_is")) {
446                 ParseElementPrintSwitch($e, $var_prefix, $switch);
447         } else {
448                 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
449         }
450 }
451
452 #####################################################################
453 # parse scalars in a structure element - pull size
454 sub ParseElementPullSwitch($$$$)
455 {
456         my($e) = shift;
457         my($var_prefix) = shift;
458         my($ndr_flags) = shift;
459         my $switch = shift;
460         my $switch_var = find_size_var($e, $switch, $var_prefix);
461
462         my $cprefix = util::c_pull_prefix($e);
463
464         my $utype = $structs{$e->{TYPE}};
465
466         check_null_pointer($switch_var);
467
468         if (!defined $utype ||
469             !util::has_property($utype, "nodiscriminant")) {
470                 my $e2 = find_sibling($e, $switch);
471                 my $type_decl = $e2->{TYPE};
472                 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
473                 if (util::is_enum($e2->{TYPE})) {
474                         $type_decl = util::enum_type_decl($e2);
475                 } elsif (util::is_bitmap($e2->{TYPE})) {
476                         $type_decl = util::bitmap_type_decl($e2);
477                 }
478                 pidl "\t\t$type_decl _level;\n";
479                 pidl "\t\tNDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, &_level));\n";
480                 if ($switch_var =~ /r->in/) {
481                         pidl "\t\tif (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {\n";
482                 } else {
483                         pidl "\t\tif (_level != $switch_var) {\n";
484                 }
485                 pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);\n";
486                 pidl "\t\t}\n";
487                 if ($switch_var =~ /r->/) {
488                         pidl "else { $switch_var = _level; }\n";
489                 }
490                 pidl "\t}\n";
491         }
492
493         my $sub_size = util::has_property($e, "subcontext");
494         if (defined $sub_size) {
495                 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
496                 pidl "\t\tNDR_CHECK(ndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE}));\n";
497                 pidl "\t}\n";
498         } else {
499                 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
500         }
501
502
503 }
504
505 #####################################################################
506 # push switch element
507 sub ParseElementPushSwitch($$$$)
508 {
509         my($e) = shift;
510         my($var_prefix) = shift;
511         my($ndr_flags) = shift;
512         my $switch = shift;
513         my $switch_var = find_size_var($e, $switch, $var_prefix);
514         my $cprefix = util::c_push_prefix($e);
515
516         check_null_pointer($switch_var);
517
518         my $utype = $structs{$e->{TYPE}};
519         if (!defined $utype ||
520             !util::has_property($utype, "nodiscriminant")) {
521                 my $e2 = find_sibling($e, $switch);
522                 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
523                 pidl "\t\tNDR_CHECK(ndr_push_$e2->{TYPE}(ndr, $switch_var));\n";
524                 pidl "\t}\n";
525         }
526
527         my $sub_size = util::has_property($e, "subcontext");
528         if (defined $sub_size) {
529                 pidl "\tif(($ndr_flags) & NDR_SCALARS) {\n";
530                 pidl "\t\tNDR_CHECK(ndr_push_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_push_$e->{TYPE}));\n";
531                 pidl "\t}\n";
532         } else {
533                 pidl "\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));\n";
534         }
535 }
536
537 #####################################################################
538 # print scalars in a structure element 
539 sub ParseElementPrintSwitch($$$)
540 {
541         my($e) = shift;
542         my($var_prefix) = shift;
543         my $switch = shift;
544         my $switch_var = find_size_var($e, $switch, $var_prefix);
545         my $cprefix = util::c_push_prefix($e);
546
547         check_null_pointer_void($switch_var);
548
549         pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n";
550 }
551
552
553 #####################################################################
554 # parse scalars in a structure element - pull size
555 sub ParseElementPullScalar($$$)
556 {
557         my($e) = shift;
558         my($var_prefix) = shift;
559         my($ndr_flags) = shift;
560         my $cprefix = util::c_pull_prefix($e);
561         my $sub_size = util::has_property($e, "subcontext");
562
563         start_flags($e);
564
565         if (util::is_inline_array($e)) {
566                 ParseArrayPull($e, "r->", "NDR_SCALARS");
567         } elsif (util::need_wire_pointer($e)) {
568                 pidl "\tNDR_CHECK(ndr_pull_ptr(ndr, &_ptr_$e->{NAME}));\n";
569                 pidl "\tif (_ptr_$e->{NAME}) {\n";
570                 pidl "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
571                 if (util::has_property($e, "relative")) {
572                         pidl "\t\tNDR_CHECK(ndr_pull_relative1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));\n";
573                 }
574                 pidl "\t} else {\n";
575                 pidl "\t\t$var_prefix$e->{NAME} = NULL;\n";
576                 pidl "\t}\n";
577         } elsif (util::need_alloc($e)) {
578                 # no scalar component
579         } elsif (my $switch = util::has_property($e, "switch_is")) {
580                 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
581         } elsif (defined $sub_size) {
582                 if (util::is_builtin_type($e->{TYPE})) {
583                         pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
584                 } else {
585                         pidl "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n";
586                 }
587         } elsif (util::is_builtin_type($e->{TYPE})) {
588                 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
589         } else {
590                 pidl "\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
591         }
592         if (my $range = util::has_property($e, "range")) {
593                 my ($low, $high) = split(/ /, $range, 2);
594                 pidl "\tif ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {\n";
595                 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");\n\t}\n";
596         }
597
598         end_flags($e);
599 }
600
601 #####################################################################
602 # parse buffers in a structure element
603 sub ParseElementPushBuffer($$$)
604 {
605         my($e) = shift;
606         my($var_prefix) = shift;
607         my($ndr_flags) = shift;
608         my $cprefix = util::c_push_prefix($e);
609         my $sub_size = util::has_property($e, "subcontext");
610
611         if (util::is_pure_scalar($e)) {
612                 return;
613         }
614
615         start_flags($e);
616
617         if (util::need_wire_pointer($e)) {
618                 pidl "\tif ($var_prefix$e->{NAME}) {\n";
619                 if (util::has_property($e, "relative")) {
620                         pidl "\t\tNDR_CHECK(ndr_push_relative2(ndr, $var_prefix$e->{NAME}));\n";
621                 }
622         }
623             
624         if (util::is_inline_array($e)) {
625                 ParseArrayPush($e, "r->", "NDR_BUFFERS");
626         } elsif (util::array_size($e)) {
627                 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
628         } elsif (my $switch = util::has_property($e, "switch_is")) {
629                 if ($e->{POINTERS}) {
630                         ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
631                 } else {
632                         ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
633                 }
634         } elsif (defined $sub_size) {
635                 if ($e->{POINTERS}) {
636                         if (util::is_builtin_type($e->{TYPE})) {
637                                 pidl "\tNDR_CHECK(ndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE}));\n";
638                         } else {
639                                 pidl "\tNDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));\n";
640                         }
641                 }
642         } elsif (util::is_builtin_type($e->{TYPE})) {
643                 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
644         } elsif ($e->{POINTERS}) {
645                 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
646         } else {
647                 pidl "\t\tNDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
648         }
649
650         if (util::need_wire_pointer($e)) {
651                 pidl "\t}\n";
652         }       
653
654         end_flags($e);
655 }
656
657 #####################################################################
658 # print buffers in a structure element
659 sub ParseElementPrintBuffer($$)
660 {
661         my($e) = shift;
662         my($var_prefix) = shift;
663         my $cprefix = util::c_push_prefix($e);
664
665         if (util::need_wire_pointer($e)) {
666                 pidl "\tif ($var_prefix$e->{NAME}) {\n";
667         }
668             
669         if (util::array_size($e)) {
670                 ParseArrayPrint($e, $var_prefix)
671         } elsif (my $switch = util::has_property($e, "switch_is")) {
672                 ParseElementPrintSwitch($e, $var_prefix, $switch);
673         } else {
674                 pidl "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
675         }
676
677         if (util::need_wire_pointer($e)) {
678                 pidl "\t}\n";
679         }       
680 }
681
682
683 #####################################################################
684 # parse buffers in a structure element - pull side
685 sub ParseElementPullBuffer($$$)
686 {
687         my($e) = shift;
688         my($var_prefix) = shift;
689         my($ndr_flags) = shift;
690         my $cprefix = util::c_pull_prefix($e);
691         my $sub_size = util::has_property($e, "subcontext");
692
693         if (util::is_pure_scalar($e)) {
694                 return;
695         }
696
697         start_flags($e);
698
699         if (util::need_wire_pointer($e)) {
700                 pidl "\tif ($var_prefix$e->{NAME}) {\n";
701                 if (util::has_property($e, "relative")) {
702                         pidl "\t\tstruct ndr_pull_save _relative_save;\n";
703                         pidl "\t\tndr_pull_save(ndr, &_relative_save);\n";
704                         pidl "\t\tNDR_CHECK(ndr_pull_relative2(ndr, $var_prefix$e->{NAME}));\n";
705                 }
706         }
707             
708         if (util::is_inline_array($e)) {
709                 ParseArrayPull($e, "r->", "NDR_BUFFERS");
710         } elsif (util::array_size($e)) {
711                 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
712         } elsif (my $switch = util::has_property($e, "switch_is")) {
713                 if ($e->{POINTERS}) {
714                         ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
715                 } else {
716                         ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
717                 }
718         } elsif (defined $sub_size) {
719                 if ($e->{POINTERS}) {
720                         if (util::is_builtin_type($e->{TYPE})) {
721                                 pidl "\tNDR_CHECK(ndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE}));\n";
722                         } else {
723                                 pidl "\tNDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));\n";
724                         }
725                 }
726         } elsif (util::is_builtin_type($e->{TYPE})) {
727                 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME}));\n";
728         } elsif ($e->{POINTERS}) {
729                 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));\n";
730         } else {
731                 pidl "\t\tNDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));\n";
732         }
733
734         if (util::need_wire_pointer($e)) {
735                 if (util::has_property($e, "relative")) {
736                         pidl "\t\tndr_pull_restore(ndr, &_relative_save);\n";
737                 }
738                 pidl "\t}\n";
739         }       
740
741         end_flags($e);
742 }
743
744 #####################################################################
745 # parse a struct
746 sub ParseStructPush($)
747 {
748         my($struct) = shift;
749         
750         if (! defined $struct->{ELEMENTS}) {
751                 return;
752         }
753
754         start_flags($struct);
755
756         # see if the structure contains a conformant array. If it
757         # does, then it must be the last element of the structure, and
758         # we need to push the conformant length early, as it fits on
759         # the wire before the structure (and even before the structure
760         # alignment)
761         my $e = $struct->{ELEMENTS}[-1];
762         if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
763                 my $size = find_size_var($e, util::array_size($e), "r->");
764                 $e->{CONFORMANT_SIZE} = $size;
765                 check_null_pointer($size);
766                 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n";
767         }
768
769         if (defined $e->{TYPE} && $e->{TYPE} eq "string" 
770             &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
771                 pidl "\tNDR_CHECK(ndr_push_uint32(ndr, ndr_string_array_size(ndr, r->$e->{NAME})));\n";
772         }
773
774         pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
775
776         pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
777
778         my $align = struct_alignment($struct);
779         pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
780
781         foreach my $e (@{$struct->{ELEMENTS}}) {
782                 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
783         }       
784
785         pidl "buffers:\n";
786         pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
787         foreach my $e (@{$struct->{ELEMENTS}}) {
788                 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
789         }
790
791         pidl "\tndr_push_struct_end(ndr);\n";
792
793         pidl "done:\n";
794
795         end_flags($struct);
796 }
797
798
799 #####################################################################
800 # generate a push function for an enum
801 sub ParseEnumPush($)
802 {
803         my($enum) = shift;
804         my($type_fn) = util::enum_type_fn($enum);
805
806         start_flags($enum);
807
808         pidl "\tNDR_CHECK(ndr_push_$type_fn(ndr, r));\n";
809
810         end_flags($enum);
811 }
812
813 #####################################################################
814 # generate a pull function for an enum
815 sub ParseEnumPull($)
816 {
817         my($enum) = shift;
818         my($type_fn) = util::enum_type_fn($enum);
819
820         start_flags($enum);
821
822         pidl "\t$type_fn v;\n";
823         pidl "\tNDR_CHECK(ndr_pull_$type_fn(ndr, &v));\n";
824         pidl "\t*r = v;\n";
825
826         end_flags($enum);
827 }
828
829 #####################################################################
830 # generate a print function for an enum
831 sub ParseEnumPrint($)
832 {
833         my($enum) = shift;
834
835         start_flags($enum);
836
837         pidl "\tconst char *val = NULL;\n\n";
838
839         pidl "\tswitch (r) {\n";
840         my $els = \@{$enum->{ELEMENTS}};
841         foreach my $i (0 .. $#{$els}) {
842                 my $e = ${$els}[$i];
843                 chomp $e;
844                 if ($e =~ /^(.*)=/) {
845                         $e = $1;
846                 }
847                 pidl "\t\tcase $e: val = \"$e\"; break;\n";
848         }
849
850         pidl "\t}\n\n\tndr_print_enum(ndr, name, \"$enum->{TYPE}\", val, r);\n";
851
852         end_flags($enum);
853 }
854
855
856 #####################################################################
857 # generate a push function for a bitmap
858 sub ParseBitmapPush($)
859 {
860         my($bitmap) = shift;
861         my($type_fn) = util::bitmap_type_fn($bitmap);
862
863         start_flags($bitmap);
864
865         pidl "\tNDR_CHECK(ndr_push_$type_fn(ndr, r));\n";
866
867         end_flags($bitmap);
868 }
869
870 #####################################################################
871 # generate a pull function for an bitmap
872 sub ParseBitmapPull($)
873 {
874         my($bitmap) = shift;
875         my($type_fn) = util::bitmap_type_fn($bitmap);
876
877         start_flags($bitmap);
878
879         pidl "\t$type_fn v;\n";
880         pidl "\tNDR_CHECK(ndr_pull_$type_fn(ndr, &v));\n";
881         pidl "\t*r = v;\n";
882
883         end_flags($bitmap);
884 }
885
886 #####################################################################
887 # generate a print function for an bitmap
888 sub ParseBintmapPrintElement($$)
889 {
890         my($e) = shift;
891         my($bitmap) = shift;
892         my($type_decl) = util::bitmap_type_decl($bitmap);
893         my($type_fn) = util::bitmap_type_fn($bitmap);
894         my($name) = $bitmap->{PARENT}->{NAME};
895         my($flag);
896
897         if ($e =~ /^(\w+) .*$/) {
898                 $flag = "$1";
899         } else {
900                 die "Bitmap: \"$name\" invalid Flag: \"$e\"";
901         }
902
903         pidl "\tndr_print_bitmap_flag(ndr, sizeof($type_decl), \"$flag\", $flag, r);\n";
904 }
905
906 #####################################################################
907 # generate a print function for an bitmap
908 sub ParseBitmapPrint($)
909 {
910         my($bitmap) = shift;
911         my($type_decl) = util::bitmap_type_decl($bitmap);
912         my($type_fn) = util::bitmap_type_fn($bitmap);
913
914         start_flags($bitmap);
915
916         pidl "\tndr_print_$type_fn(ndr, name, r);\n";
917
918         pidl "\tndr->depth++;\n";
919         foreach my $e (@{$bitmap->{ELEMENTS}}) {
920                 ParseBintmapPrintElement($e, $bitmap);
921         }
922         pidl "\tndr->depth--;\n";
923
924         end_flags($bitmap);
925 }
926
927 #####################################################################
928 # generate a struct print function
929 sub ParseStructPrint($)
930 {
931         my($struct) = shift;
932
933         if (! defined $struct->{ELEMENTS}) {
934                 return;
935         }
936
937         start_flags($struct);
938
939         pidl "\tndr->depth++;\n";
940         foreach my $e (@{$struct->{ELEMENTS}}) {
941                 ParseElementPrintScalar($e, "r->");
942         }
943         pidl "\tndr->depth--;\n";
944
945         end_flags($struct);
946 }
947
948 #####################################################################
949 # parse a struct - pull side
950 sub ParseStructPull($)
951 {
952         my($struct) = shift;
953         my $conform_e;
954
955         if (! defined $struct->{ELEMENTS}) {
956                 return;
957         }
958
959         # see if the structure contains a conformant array. If it
960         # does, then it must be the last element of the structure, and
961         # we need to pull the conformant length early, as it fits on
962         # the wire before the structure (and even before the structure
963         # alignment)
964         my $e = $struct->{ELEMENTS}[-1];
965         if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
966                 $conform_e = $e;
967         }
968
969         if (defined $e->{TYPE} && $e->{TYPE} eq "string"
970             &&  util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) {
971                 $conform_e = $e;
972         }
973
974         if (defined $conform_e) {
975                 $conform_e = $e;
976                 pidl "\tuint32_t _conformant_size;\n";
977                 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
978         }
979
980         # declare any internal pointers we need
981         foreach my $e (@{$struct->{ELEMENTS}}) {
982                 if (util::need_wire_pointer($e)) {
983                         pidl "\tuint32_t _ptr_$e->{NAME};\n";
984                 }
985         }
986
987         start_flags($struct);
988
989         pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
990
991         pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
992
993         if (defined $conform_e) {
994                 pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE}));\n";
995         }
996
997         my $align = struct_alignment($struct);
998         pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
999
1000         foreach my $e (@{$struct->{ELEMENTS}}) {
1001                 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
1002         }       
1003
1004         pidl "buffers:\n";
1005         pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1006         foreach my $e (@{$struct->{ELEMENTS}}) {
1007                 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
1008         }
1009
1010         foreach my $e (@{$struct->{ELEMENTS}}) {
1011                 CheckArraySizes($e, "r->");
1012         }
1013
1014         pidl "\tndr_pull_struct_end(ndr);\n";
1015
1016         pidl "done:\n";
1017
1018         end_flags($struct);
1019 }
1020
1021 #####################################################################
1022 # calculate size of ndr struct
1023 sub ParseStructNdrSize($)
1024 {
1025         my $t = shift;
1026         my $static = fn_prefix($t);
1027         my $sizevar;
1028
1029         pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)\n";
1030         pidl "{\n";
1031         if (my $flags = util::has_property($t, "flag")) {
1032                 pidl "\tflags |= $flags;\n";
1033         }
1034         pidl "\treturn ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});\n";
1035         pidl "}\n\n";
1036 }
1037
1038 #####################################################################
1039 # parse a union - push side
1040 sub ParseUnionPush($)
1041 {
1042         my $e = shift;
1043         my $have_default = 0;
1044
1045         start_flags($e);
1046
1047         pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1048
1049         pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n";
1050
1051 #       my $align = union_alignment($e);
1052 #       pidl "\tNDR_CHECK(ndr_push_align(ndr, $align));\n";
1053
1054         pidl "\tswitch (level) {\n";
1055         foreach my $el (@{$e->{DATA}}) {
1056                 if ($el->{CASE} eq "default") {
1057                         pidl "\tdefault:\n";
1058                         $have_default = 1;
1059                 } else {
1060                         pidl "\tcase $el->{CASE}:\n";
1061                 }
1062                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1063                         ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS");
1064                 }
1065                 pidl "\tbreak;\n\n";
1066         }
1067         if (! $have_default) {
1068                 pidl "\tdefault:\n";
1069                 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1070         }
1071         pidl "\t}\n";
1072         pidl "buffers:\n";
1073         pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1074         pidl "\tswitch (level) {\n";
1075         foreach my $el (@{$e->{DATA}}) {
1076                 if ($el->{CASE} eq "default") {
1077                         pidl "\tdefault:\n";
1078                 } else {
1079                         pidl "\tcase $el->{CASE}:\n";
1080                 }
1081                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1082                         ParseElementPushBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
1083                 }
1084                 pidl "\tbreak;\n\n";
1085         }
1086         if (! $have_default) {
1087                 pidl "\tdefault:\n";
1088                 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1089         }
1090         pidl "\t}\n";
1091         pidl "\tndr_push_struct_end(ndr);\n";
1092         pidl "done:\n";
1093         end_flags($e);
1094 }
1095
1096 #####################################################################
1097 # print a union
1098 sub ParseUnionPrint($)
1099 {
1100         my $e = shift;
1101         my $have_default = 0;
1102
1103         start_flags($e);
1104
1105         pidl "\tswitch (level) {\n";
1106         foreach my $el (@{$e->{DATA}}) {
1107                 if ($el->{CASE} eq "default") {
1108                         $have_default = 1;
1109                         pidl "\tdefault:\n";
1110                 } else {
1111                         pidl "\tcase $el->{CASE}:\n";
1112                 }
1113                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1114                         ParseElementPrintScalar($el->{DATA}, "r->");
1115                 }
1116                 pidl "\tbreak;\n\n";
1117         }
1118         if (! $have_default) {
1119                 pidl "\tdefault:\n\t\tndr_print_bad_level(ndr, name, level);\n";
1120         }
1121         pidl "\t}\n";
1122
1123         end_flags($e);
1124 }
1125
1126 #####################################################################
1127 # parse a union - pull side
1128 sub ParseUnionPull($)
1129 {
1130         my $e = shift;
1131         my $have_default = 0;
1132
1133         start_flags($e);
1134
1135         pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
1136
1137         pidl "\tNDR_CHECK(ndr_pull_struct_start(ndr));\n";
1138
1139 #       my $align = union_alignment($e);
1140 #       pidl "\tNDR_CHECK(ndr_pull_align(ndr, $align));\n";
1141
1142         pidl "\tswitch (level) {\n";
1143         foreach my $el (@{$e->{DATA}}) {
1144                 if ($el->{CASE} eq "default") {
1145                         pidl "\tdefault: {\n";
1146                         $have_default = 1;
1147                 } else {
1148                         pidl "\tcase $el->{CASE}: {\n";
1149                 }
1150                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1151                         my $e2 = $el->{DATA};
1152                         if ($e2->{POINTERS}) {
1153                                 pidl "\t\tuint32_t _ptr_$e2->{NAME};\n";
1154                         }
1155                         ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS");
1156                 }
1157                 pidl "\tbreak; }\n\n";
1158         }
1159         if (! $have_default) {
1160                 pidl "\tdefault:\n";
1161                 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1162         }
1163         pidl "\t}\n";
1164         pidl "buffers:\n";
1165         pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
1166         pidl "\tswitch (level) {\n";
1167         foreach my $el (@{$e->{DATA}}) {
1168                 if ($el->{CASE} eq "default") {
1169                         pidl "\tdefault:\n";
1170                 } else {
1171                         pidl "\tcase $el->{CASE}:\n";
1172                 }
1173                 if ($el->{TYPE} eq "UNION_ELEMENT") {
1174                         ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
1175                 }
1176                 pidl "\tbreak;\n\n";
1177         }
1178         if (! $have_default) {
1179                 pidl "\tdefault:\n";
1180                 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
1181         }
1182         pidl "\t}\n";
1183         pidl "\tndr_pull_struct_end(ndr);\n";
1184         pidl "done:\n";
1185         end_flags($e);
1186 }
1187
1188
1189 #####################################################################
1190 # parse a type
1191 sub ParseTypePush($)
1192 {
1193         my($data) = shift;
1194
1195         if (ref($data) eq "HASH") {
1196                 ($data->{TYPE} eq "STRUCT") &&
1197                     ParseStructPush($data);
1198                 ($data->{TYPE} eq "UNION") &&
1199                     ParseUnionPush($data);
1200                 ($data->{TYPE} eq "ENUM") &&
1201                     ParseEnumPush($data);
1202                 ($data->{TYPE} eq "BITMAP") &&
1203                     ParseBitmapPush($data);
1204         }
1205 }
1206
1207 #####################################################################
1208 # generate a print function for a type
1209 sub ParseTypePrint($)
1210 {
1211         my($data) = shift;
1212
1213         if (ref($data) eq "HASH") {
1214                 ($data->{TYPE} eq "STRUCT") &&
1215                     ParseStructPrint($data);
1216                 ($data->{TYPE} eq "UNION") &&
1217                     ParseUnionPrint($data);
1218                 ($data->{TYPE} eq "ENUM") &&
1219                     ParseEnumPrint($data);
1220                 ($data->{TYPE} eq "BITMAP") &&
1221                     ParseBitmapPrint($data);
1222         }
1223 }
1224
1225 #####################################################################
1226 # parse a type
1227 sub ParseTypePull($)
1228 {
1229         my($data) = shift;
1230
1231         if (ref($data) eq "HASH") {
1232                 ($data->{TYPE} eq "STRUCT") &&
1233                     ParseStructPull($data);
1234                 ($data->{TYPE} eq "UNION") &&
1235                     ParseUnionPull($data);
1236                 ($data->{TYPE} eq "ENUM") &&
1237                     ParseEnumPull($data);
1238                 ($data->{TYPE} eq "BITMAP") &&
1239                     ParseBitmapPull($data);
1240         }
1241 }
1242
1243 #####################################################################
1244 # parse a typedef - push side
1245 sub ParseTypedefPush($)
1246 {
1247         my($e) = shift;
1248         my $static = fn_prefix($e);
1249
1250         if (! needed::is_needed("push_$e->{NAME}")) {
1251 #               print "push_$e->{NAME} not needed\n";
1252                 return;
1253         }
1254
1255         if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1256                 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1257         }
1258
1259         if ($e->{DATA}->{TYPE} eq "STRUCT") {
1260                 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, struct $e->{NAME} *r)";
1261                 pidl "\n{\n";
1262                 ParseTypePush($e->{DATA});
1263                 pidl "\treturn NT_STATUS_OK;\n";
1264                 pidl "}\n\n";
1265         }
1266
1267         if ($e->{DATA}->{TYPE} eq "UNION") {
1268                 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r)";
1269                 pidl "\n{\n";
1270                 ParseTypePush($e->{DATA});
1271                 pidl "\treturn NT_STATUS_OK;\n";
1272                 pidl "}\n\n";
1273         }
1274
1275         if ($e->{DATA}->{TYPE} eq "ENUM") {
1276                 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, enum $e->{NAME} r)";
1277                 pidl "\n{\n";
1278                 ParseTypePush($e->{DATA});
1279                 pidl "\treturn NT_STATUS_OK;\n";
1280                 pidl "}\n\n";
1281         }
1282
1283         if ($e->{DATA}->{TYPE} eq "BITMAP") {
1284                 my $type_decl = util::bitmap_type_fn($e->{DATA});
1285                 pidl $static . "NTSTATUS ndr_push_$e->{NAME}(struct ndr_push *ndr, $type_decl r)";
1286                 pidl "\n{\n";
1287                 ParseTypePush($e->{DATA});
1288                 pidl "\treturn NT_STATUS_OK;\n";
1289                 pidl "}\n\n";
1290         }
1291 }
1292
1293
1294 #####################################################################
1295 # parse a typedef - pull side
1296 sub ParseTypedefPull($)
1297 {
1298         my($e) = shift;
1299         my $static = fn_prefix($e);
1300
1301         if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1302                 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1303         }
1304
1305         if (! needed::is_needed("pull_$e->{NAME}")) {
1306 #               print "pull_$e->{NAME} not needed\n";
1307                 return;
1308         }
1309
1310         if ($e->{DATA}->{TYPE} eq "STRUCT") {
1311                 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r)";
1312                 pidl "\n{\n";
1313                 ParseTypePull($e->{DATA});
1314                 pidl "\treturn NT_STATUS_OK;\n";
1315                 pidl "}\n\n";
1316         }
1317
1318         if ($e->{DATA}->{TYPE} eq "UNION") {
1319                 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r)";
1320                 pidl "\n{\n";
1321                 ParseTypePull($e->{DATA});
1322                 pidl "\treturn NT_STATUS_OK;\n";
1323                 pidl "}\n\n";
1324         }
1325
1326         if ($e->{DATA}->{TYPE} eq "ENUM") {
1327                 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, enum $e->{NAME} *r)";
1328                 pidl "\n{\n";
1329                 ParseTypePull($e->{DATA});
1330                 pidl "\treturn NT_STATUS_OK;\n";
1331                 pidl "}\n\n";
1332         }
1333
1334         if ($e->{DATA}->{TYPE} eq "BITMAP") {
1335                 my $type_decl = util::bitmap_type_fn($e->{DATA});
1336                 pidl $static . "NTSTATUS ndr_pull_$e->{NAME}(struct ndr_pull *ndr, $type_decl *r)";
1337                 pidl "\n{\n";
1338                 ParseTypePull($e->{DATA});
1339                 pidl "\treturn NT_STATUS_OK;\n";
1340                 pidl "}\n\n";
1341         }
1342 }
1343
1344
1345 #####################################################################
1346 # parse a typedef - print side
1347 sub ParseTypedefPrint($)
1348 {
1349         my($e) = shift;
1350
1351         if (defined($e->{PROPERTIES}) && !defined($e->{DATA}->{PROPERTIES})) {
1352                 $e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
1353         }
1354
1355         if ($e->{DATA}->{TYPE} eq "STRUCT") {
1356                 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, struct $e->{NAME} *r)";
1357                 pidl "\n{\n";
1358                 pidl "\tndr_print_struct(ndr, name, \"$e->{NAME}\");\n";
1359                 ParseTypePrint($e->{DATA});
1360                 pidl "}\n\n";
1361         }
1362
1363         if ($e->{DATA}->{TYPE} eq "UNION") {
1364                 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, int level, union $e->{NAME} *r)";
1365                 pidl "\n{\n";
1366                 pidl "\tndr_print_union(ndr, name, level, \"$e->{NAME}\");\n";
1367                 ParseTypePrint($e->{DATA});
1368                 pidl "}\n\n";
1369         }
1370
1371         if ($e->{DATA}->{TYPE} eq "ENUM") {
1372                 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, enum $e->{NAME} r)";
1373                 pidl "\n{\n";
1374                 ParseTypePrint($e->{DATA});
1375                 pidl "}\n\n";
1376         }
1377
1378         if ($e->{DATA}->{TYPE} eq "BITMAP") {
1379                 my $type_decl = util::bitmap_type_fn($e->{DATA});
1380                 pidl "void ndr_print_$e->{NAME}(struct ndr_print *ndr, const char *name, $type_decl r)";
1381                 pidl "\n{\n";
1382                 ParseTypePrint($e->{DATA});
1383                 pidl "}\n\n";
1384         }
1385 }
1386
1387 #####################################################################
1388 ## calculate the size of a structure
1389 sub ParseTypedefNdrSize($)
1390 {
1391         my($t) = shift;
1392         if (! needed::is_needed("ndr_size_$t->{NAME}")) {
1393                 return;
1394         }
1395         
1396         ($t->{DATA}->{TYPE} eq "STRUCT") &&
1397                 ParseStructNdrSize($t);
1398 }
1399
1400 #####################################################################
1401 # parse a function - print side
1402 sub ParseFunctionPrint($)
1403 {
1404         my($fn) = shift;
1405
1406         pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
1407         pidl "\n{\n";
1408         pidl "\tndr_print_struct(ndr, name, \"$fn->{NAME}\");\n";
1409         pidl "\tndr->depth++;\n";
1410
1411         pidl "\tif (flags & NDR_SET_VALUES) {\n";
1412         pidl "\t\tndr->flags |= LIBNDR_PRINT_SET_VALUES;\n";
1413         pidl "\t}\n";
1414
1415         pidl "\tif (flags & NDR_IN) {\n";
1416         pidl "\t\tndr_print_struct(ndr, \"in\", \"$fn->{NAME}\");\n";
1417         pidl "\tndr->depth++;\n";
1418         foreach my $e (@{$fn->{DATA}}) {
1419                 if (util::has_property($e, "in")) {
1420                         ParseElementPrintScalar($e, "r->in.");
1421                 }
1422         }
1423         pidl "\tndr->depth--;\n";
1424         pidl "\t}\n";
1425         
1426         pidl "\tif (flags & NDR_OUT) {\n";
1427         pidl "\t\tndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");\n";
1428         pidl "\tndr->depth++;\n";
1429         foreach my $e (@{$fn->{DATA}}) {
1430                 if (util::has_property($e, "out")) {
1431                         ParseElementPrintScalar($e, "r->out.");
1432                 }
1433         }
1434         if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1435                 if (util::is_scalar_type($fn->{RETURN_TYPE})) {
1436                         pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);\n";
1437                 } else {
1438                         pidl "\tndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", &r->out.result);\n";
1439                 }
1440         }
1441         pidl "\tndr->depth--;\n";
1442         pidl "\t}\n";
1443         
1444         pidl "\tndr->depth--;\n";
1445         pidl "}\n\n";
1446 }
1447
1448
1449 #####################################################################
1450 # parse a function element
1451 sub ParseFunctionElementPush($$)
1452
1453         my $e = shift;
1454         my $inout = shift;
1455
1456         if (util::array_size($e)) {
1457                 if (util::need_wire_pointer($e)) {
1458                         pidl "\tNDR_CHECK(ndr_push_ptr(ndr, r->$inout.$e->{NAME}));\n";
1459                         pidl "\tif (r->$inout.$e->{NAME}) {\n";
1460                         ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1461                         pidl "\t}\n";
1462                 } else {
1463                         ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1464                 }
1465         } else {
1466                 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1467                 if ($e->{POINTERS}) {
1468                         ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1469                 }
1470         }
1471 }       
1472
1473 #####################################################################
1474 # parse a function
1475 sub ParseFunctionPush($)
1476
1477         my($fn) = shift;
1478         my $static = fn_prefix($fn);
1479
1480         pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1481
1482         pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1483
1484         foreach my $e (@{$fn->{DATA}}) {
1485                 if (util::has_property($e, "in")) {
1486                         ParseFunctionElementPush($e, "in");
1487                 }               
1488         }
1489
1490         pidl "\nndr_out:\n";
1491         pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1492
1493         foreach my $e (@{$fn->{DATA}}) {
1494                 if (util::has_property($e, "out")) {
1495                         ParseFunctionElementPush($e, "out");
1496                 }               
1497         }
1498
1499         if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1500                 pidl "\tNDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, r->out.result));\n";
1501         }
1502     
1503         pidl "\ndone:\n";
1504         pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1505 }
1506
1507 #####################################################################
1508 # parse a function element
1509 sub ParseFunctionElementPull($$)
1510
1511         my $e = shift;
1512         my $inout = shift;
1513
1514         if (util::array_size($e)) {
1515                 if (util::need_wire_pointer($e)) {
1516                         pidl "\tNDR_CHECK(ndr_pull_ptr(ndr, &_ptr_$e->{NAME}));\n";
1517                         pidl "\tr->$inout.$e->{NAME} = NULL;\n";
1518                         pidl "\tif (_ptr_$e->{NAME}) {\n";
1519                 } elsif ($inout eq "out" && util::has_property($e, "ref")) {
1520                         pidl "\tif (r->$inout.$e->{NAME}) {\n";
1521                 } else {
1522                         pidl "\t{\n";
1523                 }
1524                 ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1525                 pidl "\t}\n";
1526         } else {
1527                 if ($inout eq "out" && util::has_property($e, "ref")) {
1528                         pidl "\tif (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\n";
1529                         pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1530                         pidl "\t}\n";
1531                 }
1532                 if ($inout eq "in" && util::has_property($e, "ref")) {
1533                         pidl "\tNDR_ALLOC(ndr, r->in.$e->{NAME});\n";
1534                 }
1535
1536                 ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1537                 if ($e->{POINTERS}) {
1538                         ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1539                 }
1540         }
1541 }
1542
1543
1544 ############################################################
1545 # allocate ref variables
1546 sub AllocateRefVars($)
1547 {
1548         my $e = shift;
1549         my $asize = util::array_size($e);
1550
1551         # note that if the variable is also an "in"
1552         # variable then we copy the initial value from
1553         # the in side
1554
1555         if (!defined $asize) {
1556                 # its a simple variable
1557                 pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});\n";
1558                 if (util::has_property($e, "in")) {
1559                         pidl "\t*r->out.$e->{NAME} = *r->in.$e->{NAME};\n";
1560                 } else {
1561                         pidl "\tZERO_STRUCTP(r->out.$e->{NAME});\n";
1562                 }
1563                 return;
1564         }
1565
1566         # its an array
1567         my $size = find_size_var($e, $asize, "r->out.");
1568         check_null_pointer($size);
1569         pidl "\tNDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);\n";
1570         if (util::has_property($e, "in")) {
1571                 pidl "\tmemcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));\n";
1572         } else {
1573                 pidl "\tmemset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));\n";
1574         }
1575 }
1576
1577
1578 #####################################################################
1579 # parse a function
1580 sub ParseFunctionPull($)
1581
1582         my($fn) = shift;
1583         my $static = fn_prefix($fn);
1584
1585         # pull function args
1586         pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)\n{\n";
1587
1588         # declare any internal pointers we need
1589         foreach my $e (@{$fn->{DATA}}) {
1590                 if (util::need_wire_pointer($e)) {
1591                         pidl "\tuint32_t _ptr_$e->{NAME};\n";
1592                 }
1593         }
1594
1595         pidl "\n\tif (!(flags & NDR_IN)) goto ndr_out;\n\n";
1596
1597         # auto-init the out section of a structure. I originally argued that
1598         # this was a bad idea as it hides bugs, but coping correctly
1599         # with initialisation and not wiping ref vars is turning
1600         # out to be too tricky (tridge)
1601         foreach my $e (@{$fn->{DATA}}) {
1602                 if (util::has_property($e, "out")) {
1603                         pidl "\tZERO_STRUCT(r->out);\n\n";
1604                         last;
1605                 }
1606         }
1607
1608         foreach my $e (@{$fn->{DATA}}) {
1609                 if (util::has_property($e, "in")) {
1610                         ParseFunctionElementPull($e, "in");
1611                 }
1612                 # we need to allocate any reference output variables, so that
1613                 # a dcerpc backend can be sure they are non-null
1614                 if (util::has_property($e, "out") && util::has_property($e, "ref")) {
1615                         AllocateRefVars($e);
1616                 }
1617         }
1618
1619         foreach my $e (@{$fn->{DATA}}) {
1620                 if (util::has_property($e, "in")) {
1621                         CheckArraySizes($e, "r->in.");
1622                 }
1623         }
1624
1625         pidl "\nndr_out:\n";
1626         pidl "\tif (!(flags & NDR_OUT)) goto done;\n\n";
1627
1628         foreach my $e (@{$fn->{DATA}}) {
1629                 if (util::has_property($e, "out")) {
1630                         ParseFunctionElementPull($e, "out");
1631                 }
1632         }
1633
1634         foreach my $e (@{$fn->{DATA}}) {
1635                 if (util::has_property($e, "out")) {
1636                         CheckArraySizes($e, "r->out.");
1637                 }
1638         }
1639
1640         if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1641                 pidl "\tNDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, &r->out.result));\n";
1642         }
1643
1644         pidl "\ndone:\n";
1645         pidl "\n\treturn NT_STATUS_OK;\n}\n\n";
1646 }
1647
1648 #####################################################################
1649 # produce a function call table
1650 sub FunctionTable($)
1651 {
1652         my($interface) = shift;
1653         my($data) = $interface->{INHERITED_DATA};
1654         my $count = 0;
1655         my $uname = uc $interface->{NAME};
1656
1657         foreach my $d (@{$data}) {
1658                 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1659         }
1660
1661         return if ($count == 0);
1662
1663         pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {\n";
1664         foreach my $d (@{$data}) {
1665                 if ($d->{TYPE} eq "FUNCTION") {
1666                         pidl "\t{\n";
1667                         pidl "\t\t\"$d->{NAME}\",\n";
1668                         pidl "\t\tsizeof(struct $d->{NAME}),\n";
1669                         pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},\n";
1670                         pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},\n";
1671                         pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}\n";
1672                         pidl "\t},\n";
1673                 }
1674         }
1675         pidl "\t{ NULL, 0, NULL, NULL }\n};\n\n";
1676
1677         # If no endpoint is set, default to the interface name as a named pipe
1678         if (! defined $interface->{PROPERTIES}->{endpoint}) {
1679                 $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\"";
1680         }
1681
1682         my @e = split / /, $interface->{PROPERTIES}->{endpoint};
1683         my $endpoint_count = $#e + 1;
1684
1685         pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {\n";
1686         foreach my $ep (@e) {
1687                 pidl "\t$ep, \n";
1688         }
1689         pidl "};\n\n";
1690
1691         pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {\n";
1692         pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings\n";
1693         pidl "};\n\n";
1694
1695         pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {\n";
1696         pidl "\t\"$interface->{NAME}\",\n";
1697         pidl "\tDCERPC_$uname\_UUID,\n";
1698         pidl "\tDCERPC_$uname\_VERSION,\n";
1699         pidl "\tDCERPC_$uname\_HELPSTRING,\n";
1700         pidl "\t$count,\n";
1701         pidl "\t$interface->{NAME}\_calls,\n";
1702         pidl "\t&$interface->{NAME}\_endpoints\n";
1703         pidl "};\n\n";
1704
1705         pidl "static NTSTATUS dcerpc_ndr_$interface->{NAME}_init(void)\n";
1706         pidl "{\n";
1707         pidl "\treturn librpc_register_interface(&dcerpc_table_$interface->{NAME});\n";
1708         pidl "}\n\n";
1709 }
1710
1711 #####################################################################
1712 # parse the interface definitions
1713 sub ParseInterface($)
1714 {
1715         my($interface) = shift;
1716         my($data) = $interface->{DATA};
1717
1718         foreach my $d (@{$data}) {
1719                 if ($d->{TYPE} eq "TYPEDEF") {
1720                     $structs{$d->{NAME}} = $d;
1721             }
1722         }
1723
1724         foreach my $d (@{$data}) {
1725                 ($d->{TYPE} eq "TYPEDEF") &&
1726                     ParseTypedefPush($d);
1727                 ($d->{TYPE} eq "FUNCTION") && 
1728                     ParseFunctionPush($d);
1729         }
1730         foreach my $d (@{$data}) {
1731                 ($d->{TYPE} eq "TYPEDEF") &&
1732                     ParseTypedefPull($d);
1733                 ($d->{TYPE} eq "FUNCTION") && 
1734                     ParseFunctionPull($d);
1735         }
1736         foreach my $d (@{$data}) {
1737                 if ($d->{TYPE} eq "TYPEDEF" &&
1738                     !util::has_property($d, "noprint")) {
1739                         ParseTypedefPrint($d);
1740                 }
1741                 if ($d->{TYPE} eq "FUNCTION" &&
1742                     !util::has_property($d, "noprint")) {
1743                         ParseFunctionPrint($d);
1744                 }
1745         }
1746
1747         foreach my $d (@{$data}) {
1748                 ($d->{TYPE} eq "TYPEDEF") && 
1749                         ParseTypedefNdrSize($d);
1750         }
1751
1752         FunctionTable($interface);
1753 }
1754
1755 sub RegistrationFunction($$)
1756 {
1757         my $idl = shift;
1758         my $filename = shift;
1759
1760         $filename =~ /.*\/ndr_(.*).c/;
1761         my $basename = $1;
1762         pidl "NTSTATUS dcerpc_$basename\_init(void)\n";
1763         pidl "{\n";
1764         pidl "\tNTSTATUS status = NT_STATUS_OK;\n";
1765         foreach my $interface (@{$idl}) {
1766                 next if $interface->{TYPE} ne "INTERFACE";
1767
1768                 my $data = $interface->{INHERITED_DATA};
1769                 my $count = 0;
1770                 foreach my $d (@{$data}) {
1771                         if ($d->{TYPE} eq "FUNCTION") { $count++; }
1772                 }
1773
1774                 next if ($count == 0);
1775
1776                 pidl "\tstatus = dcerpc_ndr_$interface->{NAME}_init();\n";
1777                 pidl "\tif (NT_STATUS_IS_ERR(status)) {\n";
1778                 pidl "\t\treturn status;\n";
1779                 pidl "\t}\n\n";
1780         }
1781         pidl "\treturn status;\n";
1782         pidl "}\n\n";
1783 }
1784
1785 #####################################################################
1786 # parse a parsed IDL structure back into an IDL file
1787 sub Parse($$)
1788 {
1789         my($idl) = shift;
1790         my($filename) = shift;
1791         my $h_filename = $filename;
1792
1793         if ($h_filename =~ /(.*)\.c/) {
1794                 $h_filename = "$1.h";
1795         }
1796
1797         open(OUT, ">$filename") || die "can't open $filename";    
1798
1799         pidl "/* parser auto-generated by pidl */\n\n";
1800         pidl "#include \"includes.h\"\n";
1801         pidl "#include \"$h_filename\"\n\n";
1802
1803         foreach my $x (@{$idl}) {
1804                 if ($x->{TYPE} eq "INTERFACE") { 
1805                         needed::BuildNeeded($x);
1806                         ParseInterface($x);
1807                 }
1808         }
1809
1810         RegistrationFunction($idl, $filename);
1811
1812         close(OUT);
1813 }
1814
1815 1;